我的sql函数中有以下代码:
if @max_chi > -999
begin
INSERT INTO CH_TABLE(X1, X2, VALUE)
VALUES(cur_out.sessionnumber, maxpos, max_chi)
commit
end
以下是SQL Server 2008查询,它给出了一个错误:
在函数中无效使用副作用运算符'INSERT'。
为什么我不允许这样做?我该怎么做才能解决这个问题?
答案 0 :(得分:68)
您无法使用函数将数据插入基表。函数返回数据。这列为the very first limitation in the documentation:
用户定义的函数不能用于执行修改数据库状态的操作。
“修改数据库状态”包括更改数据库中的任何数据(尽管表变量是OP在3年前不会关心的明显例外 - 此表变量仅存在于函数调用的持续时间内不会以任何方式影响基础表。)
您应该使用存储过程,而不是函数。
答案 1 :(得分:9)
我找到了一种方法来进行插入或更新,因此您只需要替换@sql
变量中的代码。
CREATE FUNCTION [dbo].[_tmp_func](@orderID NVARCHAR(50))
RETURNS INT
AS
BEGIN
DECLARE @sql varchar(4000), @cmd varchar(4000)
SELECT @sql = 'INSERT INTO _ord (ord_Code) VALUES (''' + @orderID + ''') '
SELECT @cmd = 'sqlcmd -S ' + @@servername +
' -d ' + db_name() + ' -Q "' + @sql + '"'
EXEC master..xp_cmdshell @cmd, 'no_output'
RETURN 1
END
答案 2 :(得分:8)
函数不能用于修改基表信息,使用存储过程。
答案 3 :(得分:3)
当您仅在声明表上使用插入/更新/删除时,有一个例外(我使用SQL 2014)。这些Insert / Update / Delete语句不能包含OUTPUT语句。另一个限制是,即使进入声明表,也不允许您进行MERGE。我将合并后的语句分解为无效的插入/更新/删除语句。
我没有将它转换为存储过程的原因是table-function比存储过程更快(即使没有MERGE)。尽管存储过程允许我使用具有统计信息的临时表。我需要表函数非常快,因为它被称为20-K次/天。此表函数永远不会更新数据库。
我还注意到函数中不允许使用NewId()和RAND()SQL函数。