52

我的 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”。

为什么我不允许这样做?我能做些什么来解决这个问题?

4

4 回答 4

78

您不能使用函数将数据插入基表。函数返回数据。这被列为文档中第一个限制

用户定义的函数不能用于执行修改数据库状态的操作。

“修改数据库状态”包括更改数据库中的任何数据(尽管表变量是一个明显的例外,OP 在 3 年前不会关心 - 此表变量仅在函数调用期间存在并且不影响以任何方式的基础表)。

您应该使用存储过程,而不是函数。

于 2013-08-22T19:44:11.023 回答
14

免责声明:这不是一个解决方案,它更像是一种测试某些东西的技巧。用户定义的函数不能用于执行修改数据库状态的操作。

我找到了一种使用 sqlcmd.exe 进行插入或更新的方法,因此您只需替换@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
于 2016-10-28T15:00:13.783 回答
8

函数不能用于修改基表信息,使用存储过程。

于 2013-08-22T19:45:50.760 回答
3

当您仅在声明表上使用插入/更新/删除时,会有一个例外(我使用的是 SQL 2014)。这些插入/更新/删除语句不能包含 OUTPUT 语句。另一个限制是您不能进行 MERGE,即使是在声明表中也是如此。我将不起作用的 Merge 语句分解为起作用的 Insert/Update/Delete 语句。

我没有将其转换为存储过程的原因是表函数比存储过程更快(即使没有 MERGE)。尽管存储过程允许我使用具有统计信息的临时表。我需要表函数非常快,因为它被称为 20-K 次/天。此表函数从不更新数据库。

我还注意到函数中不允许使用 NewId() 和 RAND() SQL 函数。

于 2017-03-27T19:34:08.340 回答