我正在尝试按照我的要求创建一个功能。
但是,当我创建或删除#tempTable
时,它会给出错误:
在函数
中无效使用副作用运算符'drop object'
我的理解是,我们无法在create
函数中执行drop
,insert
或#temptable
操作。
这是对的吗?
我的SQL:
CREATE FUNCTION [dbo].[RT_ResultFunction]
(
Id VARCHAR(4000)
)
RETURNS @RT_ResultFunction TABLE
(
Id VARCHAR(20)
, Name varchar(20)
,Balance Int
)
AS
BEGIN
IF OBJECT_ID('tempdb..#tempTable') IS NOT NULL
DROP TABLE #tempTable
SELECT Id, COUNT(Balance)
INTO #tempTable
'Balance' FROM Table1
INSERT @RT_ResultFunction
SELECT T1.ID,T1,NAME,T2,Balance
FROM Table2 T1,
#tempTable T2
WHERE T1.ID = T2.ID
RETURN
END
答案 0 :(得分:19)
这是正确的 - 你不能有副作用声明:
从这里开始:http://msdn.microsoft.com/en-us/library/aa175085(v=sql.80).aspx
BEGIN ... END块中的语句不能有任何副作用。 功能副作用是对状态的任何永久性改变 具有函数外部范围的资源,例如修改 到数据库表。可以做出的唯一改变 函数中的语句是对本地对象的更改 函数,例如本地游标或变量。修改为 数据库表,对非本地游标的操作 功能,发送电子邮件,尝试修改目录,以及 生成返回给用户的结果集是示例 无法在函数中执行的操作。
即使没有DROP
语句,您会发现,任何访问临时表的尝试都会为您提供消息(例如SELECT ... INTO #TMP
):
无法从函数中访问临时表
正如@Dems指出的那样,你可以使用表变量。因为这些是变量,所以它们在函数范围内,因此不会产生副作用。
您的功能可能会运行:
...
BEGIN
DECLARE @tempTable table (id varchar(20), rows int)
insert @tempTable
SELECT Id, COUNT(Balance)
FROM Table1
INSERT @RT_ResultFunction
SELECT T1.ID,T1,NAME,T2,Balance
FROM Table2 T1,
@tempTable T2
WHERE T1.ID = T2.ID
RETURN END
没有经过测试或其他任何事情,但你得到了要点。
答案 1 :(得分:2)
我不知道为什么你需要在这个函数中使用#temp表,或者为什么它首先是一个多语句TVF。以下将更有效(虽然我不理解@Id
参数的目的):
CREATE FUNCTION [dbo].[RT_ResultFunction]
(
@Id VARCHAR(4000)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
(
SELECT T2.ID, T2.NAME, T1.Balance
FROM
(
SELECT ID, Balance = COUNT(Balance)
FROM dbo.Table1
GROUP BY ID
) AS T1
INNER JOIN dbo.Table2 AS T2
ON T1.ID = T2.ID
);
正如Jon指出的那样,我认为它也可以重写如下,实际上我是如何开始编写它的,但我无法确认其中任何一个是否实际返回您尝试返回的数据:
CREATE FUNCTION [dbo].[RT_ResultFunction]
(
@Id VARCHAR(4000)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
(
SELECT T2.ID, T2.NAME, Balance = COUNT(T1.Balance)
FROM dbo.Table1 AS T1
INNER JOIN dbo.Table2 AS T2
ON T1.ID = T2.ID
GROUP BY T2.ID, T2.NAME
);
答案 2 :(得分:0)
删除#而不是使用@ 我没有测试过其他方面