简体   繁体   English

存储过程中的 SET QUOTED_IDENTIFIER ON 不起作用

[英]SET QUOTED_IDENTIFIER ON within the stored procedure is not working

I am using FOR XML PATH in my stored procedure and so that I need to have QUOTED_IDENTIFIER set to ON .我在存储过程中使用FOR XML PATH ,因此我需要将QUOTED_IDENTIFIER设置为ON I have it as a first statement of my stored procedure.我将它作为存储过程的第一条语句。

SET QUOTED_IDENTIFIER ON;

This is working fine all the times except I restore my database first time.除了我第一次恢复数据库外,这一直都很好用。

Just after restoring the database, I checked sp_helptext <SPName> and the stored procedure seems fine.刚刚恢复数据库后,我检查了sp_helptext <SPName>并且存储过程似乎很好。

sp_helptext

However when I browse my stored procedure from the Object Explorer and click on "Modify", it shows this:但是,当我从 Object Explorer 浏览我的存储过程并单击“修改”时,它显示如下:

调整

When I tried executing the stored procedure using EXEC <SP_Name> it throws an error当我尝试使用EXEC <SP_Name>执行存储过程时,它会抛出错误

SELECT failed because the following SET options have incorrect settings: 'QUOTED_IDENTIFIER'. SELECT 失败,因为以下 SET 选项的设置不正确:“QUOTED_IDENTIFIER”。 Verify that SET options are correct for use with indexed views and/or indexes on computed columns and/or filtered indexes and/or query notifications and/or XML data type methods and/or spatial index operations.验证 SET 选项是否正确用于索引视图和/或计算列上的索引和/或过滤索引和/或查询通知和/或 XML 数据类型方法和/或空间索引操作。

在此处输入图像描述

Can someone guide me why SQL Server is adding SET QUOTED_IDENTIFIER OFF on its own?有人可以指导我为什么 SQL 服务器自己添加SET QUOTED_IDENTIFIER OFF吗? How to get rid of it?如何摆脱它? or How can we overwrite it from within the stored procedure?或者我们如何从存储过程中覆盖它?

If I remove SET QUOTED_IDENTIFIER OFF from the top, re-execute/run it then it will work fine.如果我从顶部删除SET QUOTED_IDENTIFIER OFF ,重新执行/运行它,它就会正常工作。

My problem is - We have automated process which runs migrations/create database on every build so I can not remove it manually all the times.我的问题是 - 我们有在每次构建时运行迁移/创建数据库的自动化过程,所以我不能一直手动删除它。 I also can not set it on the database level.我也不能在数据库级别设置它。

I checked the database setting for that and its set to false but that should not make any difference right?我为此检查了数据库设置并将其设置为false但这应该没有任何区别吧? As I have it specifically SET To ON inside my stored procedure.因为我在我的存储过程中特别设置了它。

在此处输入图像描述

Thank you in advance.先感谢您。

  1. The QUOTED_IDENTIFIER database setting is irrelevant. QUOTED_IDENTIFIER 数据库设置无关紧要。 It's only a default, every client driver sets QUOTED_IDENTIFIER on connecting and overrides the database default.这只是一个默认值,每个客户端驱动程序都会在连接时设置 QUOTED_IDENTIFIER 并覆盖数据库默认值。

  2. The SET QUOTED_IDENTIFIER inside the stored procedure is irrelevant;存储过程里面的 SET QUOTED_IDENTIFIER 是无关紧要的; remove it.去掉它。

SET QUOTED_IDENTIFIER has no effect when it appears in the body of a stored procedure as static Transact-SQL.当 SET QUOTED_IDENTIFIER 作为 static Transact-SQL 出现在存储过程的主体中时,它不起作用。

SET QUOTED_IDENTIFIER SET QUOTED_IDENTIFIER

  1. The setting for QUOTED_IDENTIFIER which was in force for the batch creating the stored procedure will be stored in the catalog, and used by SSMS to script the stored procedure.对批量创建存储过程有效的 QUOTED_IDENTIFIER 设置将存储在目录中,并由 SSMS 用于编写存储过程的脚本。 It does not matter what the current session setting is, or the database default is, or what the SSMS query options are.当前的 session 设置是什么,数据库默认设置是什么,或者 SSMS 查询选项是什么都无关紧要。 If it was created with QUOTED_IDENTIFIER ON it will be scripted with QUOTED_IDENTIFIER ON.如果它是使用 QUOTED_IDENTIFIER ON 创建的,它将使用 QUOTED_IDENTIFIER ON 编写脚本。 You can see the stored setting here in sys.sql_modules.您可以在 sys.sql_modules 中查看存储的设置。

eg例如

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

So,所以,

However when I browse my stored procedure from the Object Explorer and click on "Modify", it [is scripted with QUOTED_IDENTIFER OFF].但是,当我从 Object Explorer 浏览我的存储过程并单击“修改”时,它[使用 QUOTED_IDENTIFER OFF 编写脚本]。

If the setting in sys.sql_modules different than the setting in the generated script, that would be a bug in SSMS/SMO.如果 sys.sql_modules 中的设置与生成的脚本中的设置不同,那将是 SSMS/SMO 中的错误。

And this:和这个:

在此处输入图像描述

means that the stored procedure was created with QUOTED_IDENTIFIER OFF.表示存储过程是在 QUOTED_IDENTIFIER OFF 的情况下创建的。 As you see the session setting for the session invoking the stored procedure is irrelevant since there's no TSQL being parsed when you execute a stored procedure unless it contains dynamic SQL: As you see the session setting for the session invoking the stored procedure is irrelevant since there's no TSQL being parsed when you execute a stored procedure unless it contains dynamic SQL:

When a stored procedure is created, the SET QUOTED_IDENTIFIER and SET ANSI_NULLS settings are captured and used for subsequent invocations of that stored procedure.创建存储过程时,会捕获 SET QUOTED_IDENTIFIER 和 SET ANSI_NULLS 设置并将其用于该存储过程的后续调用。

SET QUOTED_IDENTIFIER SET QUOTED_IDENTIFIER

And so yes所以是的

My problem is - We have automated process which runs migrations/create database on every build我的问题是 - 我们有自动化流程,在每次构建时运行迁移/创建数据库

This process is broken, as it's creating your proc with QUOTED_IDENTIFIER OFF.这个过程被破坏了,因为它正在使用 QUOTED_IDENTIFIER OFF 创建你的过程。 If you can't fix it you can work around it by pushing your TSQL into a dynamic batch, and setting QUOTED_IDENTIFIER ON in they dynamic SQL.如果您无法修复它,您可以通过将 TSQL 推送到动态批处理中并在动态 SQL 中设置 QUOTED_IDENTIFIER ON 来解决它。 eg例如

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

Also you can make your stored procedure create script depend on QUOTED_IDENTIFIER ON so you can't possibly create it with QUOTED_IDENTIFIER OFF, eg你也可以让你的存储过程创建脚本依赖于 QUOTED_IDENTIFIER ON 所以你不可能在 QUOTED_IDENTIFIER OFF 的情况下创建它,例如

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

fails with失败了

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

在此处输入图像描述 please test bellow statment:请测试以下语句:

USE MyDB
GO
SET QUOTED_IDENTIFIER on;
GO
EXISTS ....
BEGIN
EXEC ...
END

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM