2

我有以下查询,它使用动态数据透视以我期望的格式返回一些数据:

CREATE TABLE TEMPDOCS (DOCID INT, NAME VARCHAR(30))
CREATE TABLE PROVIDERIDS (ID INT, PARENTID INT, QUALIFIER VARCHAR(20), IDENTIFIER VARCHAR(30))
INSERT INTO TEMPDOCS VALUES (1, 'ROGER, HARPER')
INSERT INTO TEMPDOCS VALUES (2, 'WALTZ, HEALY')

INSERT INTO PROVIDERIDS VALUES (1, 1, 'DEA', 'D12345')
INSERT INTO PROVIDERIDS VALUES (2, 1, 'NPI', 'N12345')
INSERT INTO PROVIDERIDS VALUES (3, 1, 'LIC', 'L12345')
INSERT INTO PROVIDERIDS VALUES (4, 2, 'NPI', 'N23456')
INSERT INTO PROVIDERIDS VALUES (5, 2, 'REG', 'R23456')

DECLARE @cols AS NVARCHAR(MAX),
        @query  AS NVARCHAR(MAX),
        @id as int = 1;

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(QUALIFIER) 
            FROM PROVIDERIDS
            LEFT OUTER JOIN TEMPDOCS on TEMPDOCS.DOCID = PROVIDERIDS.PARENTID
            WHERE DOCID = @id
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT DOCID, NAME, ' + @cols + ' from 
            (
                select TEMPDOCS.DOCID, TEMPDOCS.NAME, PROVIDERIDS.QUALIFIER, PROVIDERIDS.IDENTIFIER FROM TEMPDOCS
                LEFT OUTER JOIN PROVIDERIDS ON PROVIDERIDS.PARENTID=TEMPDOCS.DOCID
                WHERE TEMPDOCS.DOCID = ' + CAST(@ID AS VARCHAR(30)) + '
           ) x
            pivot 
            (
                MAX(IDENTIFIER)
                FOR QUALIFIER IN (' + @cols + ')
            ) p '


execute(@query)

我想将此代码转换为返回 TABLE 的用户定义函数。我尝试这样做但无法使其工作:

CREATE FUNCTION udfGetProviderIds (@DoctorId INT)
RETURNS TABLE
AS
BEGIN
    DECLARE @cols AS NVARCHAR(MAX),
        @query  AS NVARCHAR(MAX),
        @id as int = 1;

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(QUALIFIER) 
            FROM PROVIDERIDS
            LEFT OUTER JOIN TEMPDOCS on TEMPDOCS.DOCID = PROVIDERIDS.PARENTID
            WHERE DOCID = @id
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT DOCID, NAME, ' + @cols + ' from 
            (
                select TEMPDOCS.DOCID, TEMPDOCS.NAME, PROVIDERIDS.QUALIFIER, PROVIDERIDS.IDENTIFIER FROM TEMPDOCS
                LEFT OUTER JOIN PROVIDERIDS ON PROVIDERIDS.PARENTID=TEMPDOCS.DOCID
                WHERE TEMPDOCS.DOCID = ' + CAST(@ID AS VARCHAR(30)) + '
           ) x
            pivot 
            (
                MAX(IDENTIFIER)
                FOR QUALIFIER IN (' + @cols + ')
            ) p '


    RETURN execute(@query)  
END

我收到以下错误:

Msg 102, Level 15, State 31, Procedure udfGetProviderIds, Line 32
Incorrect syntax near 'BEGIN'.

有没有办法在不声明 TABLE 和 return 子句中的结构的情况下完成这项工作?或者,有没有更好的方法来使用动态 Pivot 创建 UDF?

4

1 回答 1

0

就像 Aaron 解释的那样,您不能在 UDF 中使用动态 sql,但我可以想到一种方法,只需将所有函数定义放在存储过程中,您就可以将存储过程返回的结果放入临时表中,如下所示

CREATE PROC usp_GetProviderIds 
@DoctorId INT
AS
BEGIN
    DECLARE @cols AS NVARCHAR(MAX),
        @query  AS NVARCHAR(MAX),
        @id as int = 1;

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(QUALIFIER) 
            FROM PROVIDERIDS
            LEFT OUTER JOIN TEMPDOCS on TEMPDOCS.DOCID = PROVIDERIDS.PARENTID
            WHERE DOCID = @id
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT DOCID, NAME, ' + @cols + ' from 
            (
                select TEMPDOCS.DOCID, TEMPDOCS.NAME, PROVIDERIDS.QUALIFIER, PROVIDERIDS.IDENTIFIER FROM TEMPDOCS
                LEFT OUTER JOIN PROVIDERIDS ON PROVIDERIDS.PARENTID=TEMPDOCS.DOCID
                WHERE TEMPDOCS.DOCID = ' + CAST(@ID AS VARCHAR(30)) + '
           ) x
            pivot 
            (
                MAX(IDENTIFIER)
                FOR QUALIFIER IN (' + @cols + ')
            ) p '


    EXECUTE sp_Executesql @query  
END

然后您可以通过执行以下操作将返回的结果集放入临时表中

CREATE TABLE #TempTable (Col1, Col2.....)
INSERT INTO #TempTable
EXEC usp_GetProviderIds @DoctorId
于 2013-11-05T23:25:09.067 回答