了解 QUOTED_IDENTIFIER
我们刚刚遇到了一个问题,我们的存储过程之一抛出了错误;
SELECT failed because the following SET options have incorrect settings: 'QUOTED_IDENTIFIER'
我通过修改存储过程并将带引号的标识符设置为 ON 来修复它。问题是,我在 CREATE PROCEDURE 调用之前执行了此操作。例如;
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[InsertStuff]
我本以为这会影响 CREATE PROCEDURE 语句,但不会影响与该过程的执行有关的任何内容。
我们的脚本全部部署为 drop 和 create 脚本并通过 sqlcmd 运行。我刚刚读过此处(搜索示例:执行SQLCMD) 和 此处 sqlcmd 在引用标识符关闭的情况下执行。我已经更改了我们的脚本以包含 -I 开关以查看是否可以解决我们的问题。
我的问题是:
1) SET QUOTED_IDENTIFIER ON 语句是否仅影响 DDL CREATE PROCEDURE 语句,还是也影响存储过程的执行?我的快速测试表明是后者。
2) 由于此开关的默认设置为 ON,我假设通过我设置 sqlcmd 查询的 -I
开关不会产生不利影响。出于所有意图和目的,我假设它与复制脚本内容然后将它们粘贴到查询管理器并点击执行相同。如果我对此有误,请纠正我。我们的简单部署脚本如下;
@echo off
SET dbodir=../Schema Objects/Schemas/dbo/Programmability/Stored Procedures/
SET tpmdir=../Schema Objects/Schemas/TPM/Programmability/Stored Procedures/
echo --- Starting dbo schema
for %%f in ("%dbodir%*.sql") do (echo Running %%f.... && @sqlcmd -I -U %1 -P %2 -S %3 -d %4 -i "%dbodir%%%f")
echo --- Completed dbo schema
echo --- Starting TPM schema
for %%g in ("%tpmdir%*.sql") do (echo Running %%g.... && @sqlcmd -I -U %1 -P %2 -S %3 -d %4 -i "%tpmdir%%%g")
echo --- Completed TPM schema
pause
提前致谢
编辑:
似乎还有一些进一步info 来确定存储过程的 SET 选项的存储位置,并且对此接受的答案提供了有关适用于 SET 选项的通用优先级顺序的一般规则的一些详细信息。对此的评论还指出;
“...在过程创建时仅捕获 QUOTED_IDENTIFER 和 ANSI_NULLS 设置。” “...SET QUOTED IDENTIFIER 无法在运行时设置在存储过程中”(我的重点)。
我觉得这回答了我的第一个问题。
还有人想看第二部吗?
We just ran into a problem with one of our stored procs throwing an error;
SELECT failed because the following SET options have incorrect settings: 'QUOTED_IDENTIFIER'
I fixed it by modifiying the stored proc and setting the quoted identifier to ON. The thing is, I did this prior to the CREATE PROCEDURE call. For example;
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[InsertStuff]
I would have thought that this affected the CREATE PROCEDURE statement, but wouldn't have affected anything to do with the execution of that procedure.
Our scripts are all deployed as drop and create scripts and run via sqlcmd. I've just read that here (search for Example: Executing SQLCMD) and here that sqlcmd executes with quoted identifier off. I've changed our script to include the -I switch to see if that fixes our issues.
My questions are then;
1) Does the SET QUOTED_IDENTIFIER ON statement affect only the DDL CREATE PROCEDURE statement, or does it also affect the execution of the stored proc also? My quick test indicates the latter.
2) As the default for this switch is ON, I am presuming that by me setting the -I
switch of my sqlcmd query will have no adverse affects. For all intents and purposes, I will assume it is the same as copying the contents of the script and then pasting them into query manager and hitting execute. Please correct me if I am wrong about this. Our simple deploy script is as follows;
@echo off
SET dbodir=../Schema Objects/Schemas/dbo/Programmability/Stored Procedures/
SET tpmdir=../Schema Objects/Schemas/TPM/Programmability/Stored Procedures/
echo --- Starting dbo schema
for %%f in ("%dbodir%*.sql") do (echo Running %%f.... && @sqlcmd -I -U %1 -P %2 -S %3 -d %4 -i "%dbodir%%%f")
echo --- Completed dbo schema
echo --- Starting TPM schema
for %%g in ("%tpmdir%*.sql") do (echo Running %%g.... && @sqlcmd -I -U %1 -P %2 -S %3 -d %4 -i "%tpmdir%%%g")
echo --- Completed TPM schema
pause
Thanks in advance
Edit:
It seems as though there is some further info to determine where the SET options for stored procs are stored, and the accepted answer to this provides some details on general rules regarding generic order of precedence that applies to the SET options. The comments on this also state that;
" ...Only QUOTED_IDENTIFER and ANSI_NULLS settings are captured at procedure creation time."
"...SET QUOTED IDENTIFIER can not be set at run time inside the stored proc" (my emphasis).
I feel that answers my first question.
Any takers for the second part?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
为了寻求对
QUOTED_IDENTIFIER
的理解,我将在这里发布一些理解。简短版本
ANSI 要求在标识符周围使用引号(而不是在字符串周围)。 SQL Server 支持以下两者:
SQL Server 最初:
SELECT "Hello, world!"
--引号SELECT 'Hello, world! '
--撇号CREATE TABLE [世界上最糟糕的表名] ([Hello, world!] int)
SELECT [Hello, world!] 】 FROM 【世界上最可怕的桌子name]
ANSI(即
SET QUOTED_IDENTIFIER ON
):SELECT "Hello, world!"
-- ANSI 中字符串周围的引号不再有效SELECT 'Hello, world!'
--撇号CREATE TABLE "The world's most糟糕的表名” (“你好,世界!”int)
SELECT“你好,世界!” FROM “世界上最糟糕的表名”
长版本
最初,SQL Server 允许您使用引号 (
"..."
) 和 字符串周围的撇号('...'
)可互换(就像 Javascript 一样):SELECT "Hello, world!"
--引号< /em>选择“你好,世界!”
--撇号如果您想要一个名称表、视图、过程、列等,并且其名称会违反命名对象的所有规则,您可以将其括在方括号 (
[
,]
):这一切都有效,而且有意义。
然后出现了 ANSI
然后 ANSI 出现了,并提出了其他想法:
“...”
)括起来,'...'
) 对于字符串这意味着如果你想“引用”一个时髦的列名或表名必须使用引号:
如果您了解 SQL Server,则知道引号已经被用来表示字符串。如果您盲目地尝试像执行 T-SQL 一样执行 ANSI-SQL:这是无稽之谈,SQL Server 是这样告诉您的:
这在道德上等同于尝试执行:
这就像执行:
您必须选择加入新的 ANSI 行为
因此,Microsoft 添加了一项功能来让您选择加入 ANSI 风格的 SQL。
原始 (或
QUOTED_IDENTIFIER
关闭):SET QUOTED_IDENTIFIER ON:
SQL Server仍然允许您使用
[square方括号]
,而不是强迫您使用“引号”
。但当 QUOTED_IDENTIFIER ON 时,您不能使用“字符串周围的双引号”
,您只能使用“单引号撇号”
。Looking for an understanding of
QUOTED_IDENTIFIER
i will post some understanding here.Short version
ANSI demanded that quotation marks be used around identifiers (not around strings). SQL Server supported both:
SQL Server originally:
SELECT "Hello, world!"
--quotation markSELECT 'Hello, world!'
--apostropheCREATE TABLE [The world's most awful table name] ([Hello, world!] int)
SELECT [Hello, world!] FROM [The world's most awful table name]
ANSI (i.e.
SET QUOTED_IDENTIFIER ON
):SELECT "Hello, world!"
--quotation mark no longer valid in ANSI around stringsSELECT 'Hello, world!'
--apostropheCREATE TABLE "The world's most awful table name" ("Hello, world!" int)
SELECT "Hello, world!" FROM "The world's most awful table name"
Long Version
Originally, SQL Server allowed you to use quotation marks (
"..."
) and apostrophes ('...'
) around strings interchangeably (like Javascript does):SELECT "Hello, world!"
--quotation markSELECT 'Hello, world!'
--apostropheAnd if you wanted a name table, view, procedure, column etc with something that would otherwise violate all the rules of naming objects, you could wrap it in square brackets (
[
,]
):And that all worked, and made sense.
Then came ANSI
Then ANSI came along and had other ideas:
"..."
)'...'
) for stringsWhich means that if you wanted to "quote" a funky column or table name you must use quotation marks:
If you knew SQL Server, you knew that quotation marks were already being used to represent strings. If you blindly tried to execute that ANSI-SQL as though it were T-SQL: it's nonsense, and SQL Server told you so:
It is the moral equivalent of trying to execute:
Which is like executing:
You must opt-in to the new ANSI behavior
So Microsoft added a feature to let you opt-in to the ANSI flavor of SQL.
Original (or
QUOTED_IDENTIFIER
off):SET QUOTED_IDENTIFIER ON:
SQL Server still lets you use
[square brackets]
, rather than forcing you to use"quotation marks"
. But with QUOTED_IDENTIFIER ON, you cannot use"double quote quotation mark around strings"
, you must only use'the single quote apostrophe'
.我将以下命令保存到文本文件,然后使用 SQLCMD 执行它:
在 SQL 探查器中检查,
SQLCMD -i
连接到我的系统上的以下连接选项:但是,以下命令由SQLCMD 连接时:
然后运行我的脚本。
因此,2) 的答案是否定的 - 使用 SQLCMD -i 运行脚本与从 SSMS 执行(使用默认连接选项)不同。如果脚本需要
QUOTED_IDENTIFIER ON
,那么如果您要以这种方式执行它,则需要在开始时显式设置它。I saved the following command to a textfile, then executed it with SQLCMD:
Checking in SQL profiler,
SQLCMD -i <filename>
connects with the following connection options on my system:however the following command issued by SQLCMD when it connects:
and then it runs my script.
So, the answer to 2) is no - running a script with
SQLCMD -i
is not the same as executing from SSMS (with the default connections options). If a script requiresQUOTED_IDENTIFIER ON
, then you need to explicitly set it at the start if you're going to execute it this way.此选项指定 ANSI NULL 比较的设置。当此选项打开时,任何将值与 null 进行比较的查询都会返回 0。关闭时,任何将值与 null 进行比较的查询都会返回 null 值。
该选项指定双引号的使用设置。启用此选项后,双引号将用作 SQL Server 标识符(对象名称)的一部分。这在标识符也是 SQL Server 保留字的情况下非常有用。
This option specifies the setting for ANSI NULL comparisons. When this is on, any query that compares a value with a null returns a 0. When off, any query that compares a value with a null returns a null value.
This options specifies the setting for usage of double quotation. When this is on, double quotation mark is used as part of the SQL Server identifier (object name). This can be useful in situations in which identifiers are also SQL Server reserved words.
关于您的问题#1,原因在使用时的注意事项中说明SET 语句。它指出:
About your question #1, the reason is stated in Considerations When You Use the SET Statements. It states: