我在尝试从SQL函数返回表时遇到一些问题,其中创建表的SQL是动态编写的。
到目前为止,我有:
CREATE FUNCTION dbo.SEL_PCD
(
@COBDate AS DATETIME,
@FileName AS VARCHAR(50),
@PC AS VARCHAR(50),
@MyList AS VARCHAR(max),
DECLARE @SQL VARCHAR(max)
SET @SQL = 'SELECT * FROM
(SELECT tab1.TID FROM
(SELECT TID FROM dbo.SEL_RT('+@COBDate+','+@FileName+') WHERE BID IN ('+ @MyList +')) tab1
JOIN
(SELECT TID FROM CT WHERE (Col_Name LIKE %' + @PC + '% OR Bk LIKE %' + @PC + '%) AND FileName = ' + @FileName + ' AND COBDate = @COBDate) tab2
ON tab1.TID = tab2.TID) tab3
JOIN
(SELECT TID, Value FROM CR WHERE BID IN (' + @MyList + ') AND COBDate = ' + @COBDate + ' AND FileName = ' + @FileName + 'AND ScenID = 266) tab7
ON tab3.TID = tab7.TID'
)
RETURNS TABLE AS
RETURN
(
EXEC sp_executesql @SQL
)
GO
我收到声明SQL变量的错误。我可以通过执行命令返回表吗?
答案 0 :(得分:3)
您无法在函数内调用存储过程,包括存储过程EXECUTE
或SP_EXECUTESQL
。这意味着你不能在函数中嵌入动态sql。
您无法调用存储过程的原因是因为 的功能允许有副作用(调用它们本身不会改变任何数据 - 它们无法插入,更新或删除)。但存储过程可以。这意味着调用存储过程的函数会突然变得有副作用。
SP可以调用函数,而不是相反。
此外,SQL被编译为执行计划。那时正在使用的表和索引都变得固定。如果一个函数包含可能的动态sql;要使用的表等在编译时是未知的,并且SQL没有该功能。
在您的情况下,您的查询中唯一需要动态SQL的部分是您将逗号分隔列表作为@myList参数传递。但是,还有另一种方法。
查找在线可用的许多dbo.fn_split()
函数之一(以及SO上的许多函数)。然后使用该函数加入数据...
CREATE FUNCTION dbo.SEL_PCD( @COBDate AS DATETIME,
@FileName AS VARCHAR(50),
@PC AS VARCHAR(50),
@MyList AS VARCHAR(max)
)
RETURNS TABLE
AS
RETURN
SELECT
CR.TID,
CR.Value
FROM
dbo.SEL_RT(@COBDate, @FileName) AS RT
INNER JOIN
CT
ON CT.TID = RT.TID
INNER JOIN
CR
ON CR.TID = RT.TID
WHERE
(CT.Col_Name LIKE '%'+@PC+'%' OR CT.Bk LIKE '%'+@PC+'%')
AND CT.FileName = @FileName
AND CT.COBDate = @COBDate
AND CR.FileName = @FileName
AND CR.COBDate = @COBDate
AND CR.ScenID = 266
AND RT.BID IN (SELECT id FROM dbo.fn_split(@myList, ',') AS my_list)
AND CR.BID IN (SELECT id FROM dbo.fn_split(@myList, ',') AS my_list)
答案 1 :(得分:3)
试试这个:
CREATE PROCEDURE dbo.SEL_PCD
(
@COBDate DATETIME,
@FileName VARCHAR(50),
@PC VARCHAR(50),
@MyList VARCHAR(max)
) AS
DECLARE @SQL VARCHAR(max)
SELECT @SQL = 'SELECT * FROM
(SELECT tab1.TID FROM
(SELECT TID FROM dbo.SEL_RT('+@COBDate+','+@FileName+') WHERE BID IN ('+ @MyList +')) tab1
JOIN
(SELECT TID FROM CT WHERE (Col_Name LIKE %' + @PC + '% OR Bk LIKE %' + @PC + '%) AND FileName = ' + @FileName + ' AND COBDate = @COBDate) tab2
ON tab1.TID = tab2.TID) tab3
JOIN
(SELECT TID, Value FROM CR WHERE BID IN (' + @MyList + ') AND COBDate = ' + @COBDate + ' AND FileName = ' + @FileName + 'AND ScenID = 266) tab7
ON tab3.TID = tab7.TID'
EXEC(@SQL)
<强>功能强>
存储过程
答案 2 :(得分:0)
你不能在函数
中使用execute命令CREATE PROCEDURE dbo.SEL_PCD4
(
@COBDate AS DATETIME,
@FileName AS VARCHAR(50),
@PC AS VARCHAR(50),
@MyList AS VARCHAR(max)
) AS
DECLARE @SQL VARCHAR(max)
SET @SQL = 'SELECT * FROM
(SELECT tab1.TID FROM
(SELECT TID FROM dbo.SEL_RT('+@COBDate+','+@FileName+') WHERE BID IN ('+ @MyList +')) tab1
JOIN
(SELECT TID FROM CT WHERE (Col_Name LIKE %' + @PC + '% OR Bk LIKE %' + @PC + '%) AND FileName = ' + @FileName + ' AND COBDate = @COBDate) tab2
ON tab1.TID = tab2.TID) tab3
JOIN
(SELECT TID, Value FROM CR WHERE BID IN (' + @MyList + ') AND COBDate = ' + @COBDate + ' AND FileName = ' + @FileName + 'AND ScenID = 266) tab7
ON tab3.TID = tab7.TID'
EXEC sp_executesql @SQL
GO