EXEC and Set Quoted_Identifier

3

我有一个存储过程[A],它创建了另一个存储过程[B]。

[A]永远不会由最终用户运行,并且没有参数或其他不受信任的数据。相反,它仅用于自动化创建复杂的SP [B]。除非[A]的内部发生变化,否则[A]将始终具有相同的结果。因此,我认为这是安全的。

[B]需要开启Quoted_Identifiers选项,因为它使用xml。

如果我复制并粘贴生成的SP,则可以正常工作,但如果让[A]使用EXEC创建它,则在运行时SP失败。

我尝试在[B]内部添加SET QUOTED_IDENTIFIERS ON,但似乎没有任何效果。

如果使用sp_ExecuteSQL也会出现相同的问题。我还尝试在调用[B]之前将其设置为ON,但似乎也没有效果(但是在始终开启的情况下,它为什么会有效呢)

我的猜测是,EXEC和sp_ExecuteSQL始终使用OFF选项进行设置,并且SET命令由解析器而不是SQL引擎本身处理。那么我该如何使EXEC正确创建存储过程?

1个回答

3
您需要在创建存储过程A时将QUOTED_IDENTIFIER设置为ON。注意:

当创建存储过程时,SET QUOTED_IDENTIFIER和SET ANSI_NULLS设置将被记录并用于该存储过程的后续调用。

这意味着创建存储过程的任何存储过程都会传递在其创建期间生效的设置。例如:

set quoted_identifier on
go
create procedure ABC
as
    exec('create procedure DEF as')
go
set quoted_identifier off
go
exec ABC
go
select definition,uses_quoted_identifier from sys.sql_modules
where object_id=OBJECT_ID('DEF')

产生:

definition                             uses_quoted_identifier
-------------------------------------- ----------------------
create procedure DEF as                1

嗯,我以为我已经尝试过这个了,但可能是我把设置放错了地方。我会再试一次。(将其关闭对于[A]来说实际上是可取的,因为存在字符串内部,但不是必需的) - DJL
@Damien - 我很抱歉插入这个帖子,但我有一个非常相似的问题,涉及从单个sproc中创建/修改多个sprocs(具有不同的QUOTED_IDENTIFIER值)。如果您能看一下,我会非常感激...尽管我认为从上面已经知道答案了。 - freefaller

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接