了解QUOTED_IDENTIFIER

Mr *_*ose 10 sql-server settings ddl

我们遇到了一个问题,我们的一个存储过程抛出错误;

SELECT failed because the following SET options have incorrect settings: 'QUOTED_IDENTIFIER'
Run Code Online (Sandbox Code Playgroud)

我通过修改存储的proc并将引用的标识符设置为ON来修复它.问题是,我在CREATE PROCEDURE调用之前做了这个.例如;

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[InsertStuff]
Run Code Online (Sandbox Code Playgroud)

我原以为这会影响CREATE PROCEDURE语句,但不会影响该程序的执行.

我们的脚本都被部署为drop并创建脚本并通过sqlcmd运行.我刚刚在这里阅读(搜索示例:执行SQLCMD),这里 sqlcmd执行时带引号标识符off.我已经更改了我们的脚本以包含-I开关,以查看是否可以解决我们的问题.

那时我的问题是;

1)SET QUOTED_IDENTIFIER ON语句是否仅影响DDL CREATE PROCEDURE语句,还是它也影响存储过程的执行?我的快速测试表明后者.

2)由于此开关的默认设置为ON,我假设通过设置-I我的sqlcmd查询的开关将没有不利影响.对于所有意图和目的,我将假设它与复制脚本的内容然后将它们粘贴到查询管理器并执行命令相同.如果我错了,请纠正我.我们的简单部署脚本如下;

@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
Run Code Online (Sandbox Code Playgroud)

提前致谢

编辑:

似乎有一些进一步的信息来确定存储过程的SET选项的存储位置,并且接受的答案提供了有关适用于SET选项的一般优先顺序的一般规则的一些细节.对此的评论也表明了这一点;

"...在程序创建时仅捕获QUOTED_IDENTIFER和ANSI_NULLS设置." "... SET QUOTED IDENTIFIER 无法在存储过程中的运行时设置 "(我的重点).

我觉得这回答了我的第一个问题.

第二部分的任何接受者?

Ian*_*oyd 9

寻找理解QUOTED_IDENTIFIER我将在这里发表一些理解.

精简版

ANSI要求在标识符周围使用引号(不是在字符串周围).SQL Server支持两者:

SQL Server最初:

  • SELECT "Hello, world!" - 引号
  • SELECT 'Hello, world!' --apostrophe
  • CREATE TABLE [The world's most awful table name] ([Hello, world!] int)
  • SELECT [Hello, world!] FROM [The world's most awful table name]

ANSI(即SET QUOTED_IDENTIFIER ON):

  • SELECT "Hello, world!" - 在ANSI周围的字符串中,引号不再有效
  • SELECT 'Hello, world!' --apostrophe
  • CREATE TABLE "The world's most awful table name" ("Hello, world!" int)
  • SELECT "Hello, world!" FROM "The world's most awful table name"

古老的时代

最初,SQL Server允许您在字符串之间交替使用引号("...")和撇号('...')(如Javascript一样):

  • SELECT "Hello, world!" - 引号
  • SELECT 'Hello, world!' --apostrophe

如果你想要一个名称表,视图,过程,列等,否则会违反所有命名对象的规则,你可以将它包装在方括号([,])中:

CREATE TABLE [The world's most awful table name] ([Hello, world!] int)
SELECT [Hello, world!] FROM [The world's most awful table name]
Run Code Online (Sandbox Code Playgroud)

这一切都有效,并且有意义.

然后是ANSI

然后ANSI出现并有其他想法:

  • 如果你有一个时髦的名字,请用引号括起来("...")
  • 使用撇号('...')表示字符串
  • 我们甚至不关心你的方括号

这意味着如果你想"引用"一个时髦的列或表名,你必须使用引号:

SELECT "Hello, world!" FROM "The world's most awful table name"
Run Code Online (Sandbox Code Playgroud)

如果您了解SQL Server,则您知道引号已经被用于表示字符串.如果你盲目地尝试执行ANSI-SQL就像它是T-SQL一样:这是无稽之谈,而SQL Server告诉你:

Msg 102, Level 15, State 1, Line 8
Incorrect syntax near 'The world's most awful table name'.
Run Code Online (Sandbox Code Playgroud)

您必须选择加入新的ANSI行为

因此,Microsoft添加了一项功能,让您选择加入ANSI的ANSI风格.

原版的

SELECT "Hello, world!" --valid
SELECT 'Hello, world!' --valid
Run Code Online (Sandbox Code Playgroud)

SET QUOTED_IDENTIFIER ON

SELECT "Hello, world!" --INVALID
SELECT 'Hello, world!' --valid
Run Code Online (Sandbox Code Playgroud)

SQL Server仍允许您使用[square brackets],而不是强制您使用"quotatio marks".但是使用QUOTED_IDENTIFIER,你不能使用"double quote quotation mark around strings",你必须只使用'the single quote apostrophe'.


Ed *_*per 3

我将以下命令保存到文本文件中,然后使用 SQLCMD 执行它:

SET QUOTED_IDENTIFIER ON
SET QUOTED_IDENTIFIER OFF
Run Code Online (Sandbox Code Playgroud)

检查 SQL 探查器,SQLCMD -i <filename>使用我的系统上的以下连接选项进行连接:

-- network protocol: LPC
set quoted_identifier on
...
Run Code Online (Sandbox Code Playgroud)

但是 SQLCMD 在连接时发出以下命令:

SET QUOTED_IDENTIFIER OFF SET TEXTSIZE 4096
Run Code Online (Sandbox Code Playgroud)

然后它运行我的脚本。

因此,2) 的答案是否定的 - 运行脚本与SQLCMD -i从 SSMS 执行(使用默认连接选项)不同。如果脚本需要QUOTED_IDENTIFIER ON,那么如果您打算以这种方式执行它,则需要在开始时显式设置它。

  • 嗨艾德。我认为你使用了正确的开关,但大小写不正确。我指的是大写的 I。小写的 -i 指定文件名,大写的 -I 指的是引用的标识符。http://msdn.microsoft.com/en-us/library/ms162773.aspx。我的主要问题是,使用 -I 开关是否与通过 Management Studio 运行命令有效相同?不过使用探查器是个好主意。我可能会进一步调查这一点。 (2认同)
  • @穆斯先生 - 我的错误。在这种情况下,是的,这应该与通过 SSMS 执行相同 (2认同)