【问题标题】:存储过程中的 SET QUOTED_IDENTIFIER ON 不起作用
【发布时间】:2022-01-23 02:12:00
【问题描述】:

我在存储过程中使用FOR XML PATH,因此我需要将QUOTED_IDENTIFIER 设置为ON。我把它作为我的存储过程的第一条语句。

SET QUOTED_IDENTIFIER ON;

除了我第一次恢复我的数据库之外,这一直工作正常。

刚恢复数据库后,我检查了sp_helptext <SPName>,存储过程似乎没问题。

但是,当我从对象资源管理器中浏览我的存储过程并单击“修改”时,它会显示:

当我尝试使用 EXEC <SP_Name> 执行存储过程时,它会引发错误

SELECT 失败,因为以下 SET 选项的设置不正确:“QUOTED_IDENTIFIER”。验证 SET 选项是否适用于索引视图和/或计算列上的索引和/或过滤索引和/或查询通知和/或 XML 数据类型方法和/或空间索引操作。

有人可以指导我为什么 SQL Server 自己添加SET QUOTED_IDENTIFIER OFF 吗?如何摆脱它?或者我们如何从存储过程中覆盖它?

如果我从顶部删除SET QUOTED_IDENTIFIER OFF,重新执行/运行它就会正常工作。

我的问题是 - 我们有自动化流程,在每次构建时都会运行迁移/创建数据库,所以我不能一直手动删除它。 我也不能在数据库级别设置它。

我检查了数据库设置并将其设置为false,但这应该没有什么区别吧?因为我在我的存储过程中专门设置了它。

提前谢谢你。

【问题讨论】:

  • 停止你正在做的事情。召集整个团队并讨论此设置、其工作原理(阅读文档)、为什么默认设置为关闭以及谁更改了此设置(以及原因)。
  • 您不应将此设置为您的过程文本的一部分,此设置是您创建的每个对象的元数据的一部分,并且取决于对象创建时的连接设置创建的。它应该是 ON - 没有理由在最新版本的 SQL Server 中将其设置为关闭,这样做可能会对某些需要它的功能产生不利影响,正如您从错误文本中看到的那样。

标签: sql-server quoted-identifier


【解决方案1】:
  1. QUOTED_IDENTIFIER 数据库设置无关紧要。这只是一个默认值,每个客户端驱动程序都会在连接时设置 QUOTED_IDENTIFIER 并覆盖数据库默认值。

  2. 存储过程中的 SET QUOTED_IDENTIFIER 是无关紧要的;删除它。

SET QUOTED_IDENTIFIER 在出现在 存储过程为静态 Transact-SQL。

SET QUOTED_IDENTIFIER

  1. 对批量创建存储过程有效的 QUOTED_IDENTIFIER 设置将存储在目录中,并由 SSMS 用于编写存储过程的脚本。当前会话设置是什么、数据库默认设置是什么或 SSMS 查询选项是什么都无关紧要。如果它是使用 QUOTED_IDENTIFIER ON 创建的,它将使用 QUOTED_IDENTIFIER ON 编写脚本。您可以在 sys.sql_modules 中查看此处存储的设置。

例如

select uses_quoted_identifier
from sys.sql_modules
where object_id = object_id('MyProc')

所以,

但是,当我从对象资源管理器浏览我的存储过程并单击“修改”时,它[使用 QUOTED_IDENTIFER OFF 编写脚本]。

如果 sys.sql_modules 中的设置与生成脚本中的设置不同,那将是 SSMS/SMO 中的错误。

还有这个:

表示存储过程是在 QUOTED_IDENTIFIER OFF 的情况下创建的。如您所见,调用存储过程的会话的会话设置是无关紧要的。

创建存储过程时,SET QUOTED_IDENTIFIER 和 SET ANSI_NULLS 设置被捕获并用于后续调用 那个存储过程。

SET QUOTED_IDENTIFIER

此存储过程的设置还控制存储过程中动态 SQL 的 QUOTED_IDENTIFIER 设置。但在动态 SQL 中,您可以更改设置。

所以是的

我的问题是 - 我们有自动化流程,在每次构建时运行迁移/创建数据库

此过程已损坏,因为它正在创建您的 proc 并关闭 QUOTED_IDENTIFIER。如果您无法修复它,您可以通过将 TSQL 推送到动态批处理中并在动态 SQL 中设置 QUOTED_IDENTIFIER ON 来解决它。例如

set quoted_identifier off
go
create or alter procedure foo
as
begin
  exec ('set quoted_identifier on; select * from "sys"."objects"')

end
go

exec foo --suceeds

你也可以让你的存储过程创建脚本依赖于 QUOTED_IDENTIFIER ON 所以你不可能在 QUOTED_IDENTIFIER OFF 的情况下创建它,例如

set quoted_identifier off
go
create or alter procedure foo
as
begin
  select * from "sys"."objects" 
end

失败

Msg 102, Level 15, State 1, Procedure foo, Line 4 [Batch Start Line 2]
Incorrect syntax near 'sys'.

【讨论】:

  • 感谢您的详细解释和帮助。
猜你喜欢
  • 2019-07-12
  • 2016-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多