关于如何在 Sql 服务器中的函数内执行字符串的技巧
Tricks on how to execute string inside a function in Sql Server
过程 FunctionX,第 345 行
Invalid use of a side-effecting operator 'EXECUTE STRING' within a
function.
当我在 SQL Server 2012 中的函数内执行动态语句时出现上述错误。
有解决方法吗?有什么技巧吗?
PS: sproc(存储过程)太长,无法按原样插入函数内部。
DECLARE @execsql NVARCHAR(2000)
Set @execsql = 'INSERT INTO @TABLE1 EXEC SPROC1 ' + @ID_COMPANY + ',' + @ID_COUNTRY
exec (@execsql)
非常感谢。
此外,我还需要能够在函数内部删除。我知道这与函数的定义相矛盾,但我想知道是否有一些技巧可以使用
没有什么技巧,看The Curse and Blessings of Dynamic SQL
Dynamic SQL in User-Defined Functions
This is very simple: you cannot use dynamic SQL from used-defined
functions written in T-SQL. This is because you are not permitted to do
anything in a UDF that could change the database state (as the UDF may
be invoked as part of a query). Since you can do anything from dynamic
SQL, including updates, it is obvious why dynamic SQL is not
permitted.
I've seen more than one post on the newsgroups where people have been
banging their head against this. But if you want to use dynamic SQL in
a UDF, back out and redo your design. You have hit a roadblock, and in
SQL 2000 there is no way out.
In SQL 2005 and later, you could implement your function as a CLR
function. Recall that all data access from the CLR is dynamic SQL.
(You are safe-guarded, so that if you perform an update operation from
your function, you will get caught.) A word of warning though: data
access from scalar UDFs can often give performance problems. If you
say
SELECT ... FROM tbl WHERE dbo.MyUdf(somecol) = @value
and MyUdf performs data access, you have more or less created a hidden
cursor.
我在多行 table 值函数中使用动态 OPENQUERY 语句时遇到了同样的问题。 SQL 服务器试图阻止只有 db_datareader 访问权限的用户执行 SQL 注入,这些用户可以 select 使用这些功能。长话短说,尽可能多地删除单引号,找到一种不使用 EXEC 来做同样事情的方法。
而不是这样做:
Set @execsql = 'INSERT INTO @TABLE1 EXEC SPROC1 ' + @ID_COMPANY + ',' + @ID_COUNTRY
做这样的事情:
INSERT INTO @TABLE1
SELECT *
FROM --some unfiltered version of the table your stored procedure uses
WHERE company = @ID_COMPANY
AND country = @ID_COUNTRY
由于您是从存储过程中调用函数,因此您已经可以确定 table 是最新的。在我的例子中,我能够每天早上使用存储过程刷新函数的底层 table 一次。您也可以使用触发器来做到这一点。
过程 FunctionX,第 345 行
Invalid use of a side-effecting operator 'EXECUTE STRING' within a function.
当我在 SQL Server 2012 中的函数内执行动态语句时出现上述错误。 有解决方法吗?有什么技巧吗?
PS: sproc(存储过程)太长,无法按原样插入函数内部。
DECLARE @execsql NVARCHAR(2000)
Set @execsql = 'INSERT INTO @TABLE1 EXEC SPROC1 ' + @ID_COMPANY + ',' + @ID_COUNTRY
exec (@execsql)
非常感谢。
此外,我还需要能够在函数内部删除。我知道这与函数的定义相矛盾,但我想知道是否有一些技巧可以使用
没有什么技巧,看The Curse and Blessings of Dynamic SQL
Dynamic SQL in User-Defined Functions
This is very simple: you cannot use dynamic SQL from used-defined functions written in T-SQL. This is because you are not permitted to do anything in a UDF that could change the database state (as the UDF may be invoked as part of a query). Since you can do anything from dynamic SQL, including updates, it is obvious why dynamic SQL is not permitted.
I've seen more than one post on the newsgroups where people have been banging their head against this. But if you want to use dynamic SQL in a UDF, back out and redo your design. You have hit a roadblock, and in SQL 2000 there is no way out.
In SQL 2005 and later, you could implement your function as a CLR function. Recall that all data access from the CLR is dynamic SQL. (You are safe-guarded, so that if you perform an update operation from your function, you will get caught.) A word of warning though: data access from scalar UDFs can often give performance problems. If you say
SELECT ... FROM tbl WHERE dbo.MyUdf(somecol) = @value
and MyUdf performs data access, you have more or less created a hidden cursor.
我在多行 table 值函数中使用动态 OPENQUERY 语句时遇到了同样的问题。 SQL 服务器试图阻止只有 db_datareader 访问权限的用户执行 SQL 注入,这些用户可以 select 使用这些功能。长话短说,尽可能多地删除单引号,找到一种不使用 EXEC 来做同样事情的方法。
而不是这样做:
Set @execsql = 'INSERT INTO @TABLE1 EXEC SPROC1 ' + @ID_COMPANY + ',' + @ID_COUNTRY
做这样的事情:
INSERT INTO @TABLE1
SELECT *
FROM --some unfiltered version of the table your stored procedure uses
WHERE company = @ID_COMPANY
AND country = @ID_COUNTRY
由于您是从存储过程中调用函数,因此您已经可以确定 table 是最新的。在我的例子中,我能够每天早上使用存储过程刷新函数的底层 table 一次。您也可以使用触发器来做到这一点。