해결되지 않는 사용자정의 함수 구현이 생겨서... 또 다시 문의를 드립니다.
테이블 반환 함수는 뷰를 대신해서 Table Data 형식을 반환하는데...
반환 함수는 inline 과 MultiStatement 두가지 형식으로 구분되지요....
일단 제가 구현하고 싶은 내용의 샘플링을 해보면...
테이블명과 출력할 row 수를 입력 받아서 테이블 형태로 return 하는 것이 가장 적절한 샘플이 될 것 같습니다.
컬럼수가 고정되어 있다면 MultiStatement 형태로 return될 Table의 컬럼 형태를 지정해서 하면 되지만...
조회할 테이블마다 컬럼의 수와 컬럼명이 모두 다르다고 가정했을때 MultiStatement로는 지정이 불가하여
Inline 형태로 하려고 합니다.
컬럼명은 DBA_TAB_COLUMNS 에서 조회해서 Cursor를 돌려서 Query를 만드어 Varchar 변수에 담았다가
Return하려고 하는 생각을 하고 있습니다.
사용자 입장에서는 SELECT * FROM FN_SELECT_TABLE('TMP_TABLE', 100) 이라고 조회를 하면...
100개의 Row가 조회를 되는 형태를 예제라고 할 수 있습니다.
문제는 'TMP_TABLE' 에 해당하는 테이블 컬럼이 테이블마다 다르기 때문에 MultiStatement 형태로 Return Table 의 형태를
지정할 수 없다는게 문제입니다.
요약하면 아래와 같습니다.
1. 파라미터로 테이블명과 추출 row 수를 입력 받는다.
CREATE FUNCTION [dbo].[FN_SELECT_TABLE]
(
@I_TABLE_NAME VARCHAR(100), -- 조회할 테이블명
@I_ROW_CNT INT -- 조회할 ROW COUNT (0 인경우 전체)
)
2. 전달받은 테이블명을 DBA_TAB_COLUMNS 에서 조회하여 컬럼명을 조회한다.
SELECT COLUMN_NAME FROM DBA_TAB_COLUMNS WHERE TABLE_NAME = @I_TABLE_NAME
3. 조회된 COLUMN_NAME 의 수만큼 CURSOR를 돌려서 임시 VARCHAR 변수에 저장한다.
@TMP_SQL = 'SELECT TOP ' + @I_ROW_CNT
--LOOP 시작
@TMP_SQL = @TMP_SQL + COLUMN_NAME + ','
--LOOP 종료
@TMP_SQL = @TMP_SQL + ' FROM ' + @I_TABLE_NAME
4. 동적으로 생성된 쿼리(@TMP_SQL)를 실행해서 TABLE 형태로 RETURN 한다.
대략적인 샘플링은 이렇습니다.
고수님들의 지도편달 부탁드립니다. ^^;
Comment 2
-
건우아빠
2019.01.10 15:35
-
난나야78
2019.01.10 16:48
--함수가 안되서 프로시저로 작성하였습니다. ^^ALTER PROCEDURE [dbo].[SP_TABLE_SELECT_WITH_COMMENT]@I_TABLE_NM VARCHAR(50),@I_ROW_CNT INTASBEGINSET NOCOUNT ON; -- PROCEDURE OPTION SETDECLARE@TMP_COLUMN VARCHAR(MAX),@TMP_SELECT VARCHAR(100),@TMP_SQL VARCHAR(MAX)DECLARE@TMP_COLUMN_NM VARCHAR(100),@TMP_COLUMN_COMMENT VARCHAR(100)DECLARE @ELEMENTS TABLE(Number INT IDENTITY(1,1),Column_NM VARCHAR(100),Column_Comment VARCHAR(200))DECLARE @IDX INTDECLARE @COUNT INTINSERT INTO @ELEMENTS (Column_NM, Column_Comment)SELECT CONVERT(VARCHAR(100), CO.NAME) AS Column_NM, (SELECT CONVERT(VARCHAR(100), VALUE) FROM SYS.EXTENDED_PROPERTIES WHERE MAJOR_ID = TA.OBJECT_ID AND MINOR_ID = CO.COLUMN_ID ) AS Column_CommentFROM SYS.TABLES AS TA WITH (NOLOCK)LEFT JOIN SYS.ALL_COLUMNS AS CO WITH (NOLOCK)ON TA.OBJECT_ID = CO.OBJECT_IDWHERE TA.NAME = @I_TABLE_NMORDER BY CO.COLUMN_IDSET @IDX = 1SET @TMP_COLUMN = ''SET @TMP_SQL = ''SELECT @COUNT = MAX(Number)FROM @ELEMENTSWHILE @IDX <= @COUNTBEGINSELECT @TMP_COLUMN_NM = Column_NM, @TMP_COLUMN_COMMENT = REPLACE(REPLACE(Column_Comment,']','|'),'[','|')FROM @ELEMENTSWHERE Number = @IDXSELECT @TMP_COLUMN = @TMP_COLUMN + @TMP_COLUMN_NM + ' [' + @TMP_COLUMN_NM + '-' + @TMP_COLUMN_COMMENT + '], 'SELECT @IDX = @IDX + 1ENDIF LEN(@TMP_COLUMN) > 8BEGINSELECT @TMP_COLUMN = SUBSTRING( @TMP_COLUMN, 1, LEN(@TMP_COLUMN)-1 ) --마지막 , 삭제END-- SELECTIF ISNULL(@I_ROW_CNT, 0) = 0BEGINSET @TMP_SELECT = 'SELECT 'ENDELSEBEGINSET @TMP_SELECT = 'SELECT TOP ' + CONVERT(VARCHAR(100),@I_ROW_CNT) + ' 'ENDSET @TMP_SQL = @TMP_SELECT + @TMP_COLUMN + ' FROM ' + @I_TABLE_NMPRINT @TMP_SQLEXECUTE(@TMP_SQL)END
사용자함수에서는 exec를 사용 못해서 동적 퀄리는 불가능 할듯 합니다.