Vac*_*ano 22 sql sql-server sql-server-2012
注意:我检查了理解QUOTED_IDENTIFIER并且它没有回答我的问题.
我让我的DBA运行我在Prod服务器上制作的索引(他们查看并批准了它).
它就像我想要的那样加速了我的查询.但是,我开始遇到这样的错误:
作为开发人员,我通常会忽略这些设置.它从来都不重要.(9年以上).好吧,今天很重要.
我去看了一个失败的sprocs,它在创建sproc之前有这个:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Run Code Online (Sandbox Code Playgroud)
任何人都可以从应用程序开发人员的角度告诉我这些set语句的作用是什么? (在我的索引创建语句之前添加上面的代码并没有解决问题.)
注意:以下是我的索引的示例:
CREATE NONCLUSTERED INDEX [ix_ClientFilerTo0]
ON [ClientTable] ([Client])
INCLUDE ([ClientCol1],[ClientCol2],[ClientCol3] ... Many more columns)
WHERE Client = 0
CREATE NONCLUSTERED INDEX [IX_Client_Status]
ON [OrderTable] ([Client],[Status])
INCLUDE ([OrderCol1],[OrderCol2],[OrderCol3],[OrderCol4])
WHERE [Status] <= 7
GO
Run Code Online (Sandbox Code Playgroud)
RBa*_*ung 59
好的,从应用程序开发人员的角度来看,以下是这些设置的作用:
此设置控制".."SQL编译器如何解释引号.当QUOTED_IDENTIFIER为ON时,引号被视为括号([...]),可用于引用SQL对象名称,如表名,列名等.当它为OFF(不推荐)时,引号被视为撇号('..'),可以使用引用SQL命令中的文本字符串.
此设置控制当您尝试使用除ISNULL 之外的任何比较运算符时发生的情况.当它为ON时,这些比较遵循标准,该标准表示与NULL相比总是失败(因为它不是值,它是一个标志)并返回FALSE.当此设置为OFF(真的不推荐),你可以成功地把它像一个价值和用途=,<>等它并获得尽可能appropiate回TRUE.
处理此问题的正确方法是使用IS(ColumnValue IS NULL ..).
此设置控制是否在字符串表达式中使用NULL"Propogate".当此设置为ON时,它遵循标准,并且像'some string' + NULL ..always 一样的表达式返回NULL.因此,在一系列字符串连接中,一个NULL可以导致整个表达式返回NULL.将其关闭(也不建议)将导致NULL被视为空字符串,因此'some string' + NULL只需求值为'some string'.
处理此问题的正确方法是使用COALESCE(或ISNULL)函数:'some string' + COALESCE(NULL, '') ...
Ian*_*oyd 13
我发现文档,博客文章,Stackoverflow回答无助于解释启用QUOTED_IDENTIFIER意味着什么.
最初,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出现并有其他想法:
"...")'...')表示字符串这意味着如果你想"引用"一个时髦的列或表名,你必须使用引号:
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)
因此,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)
这些天每个人都有SET QUOTED_IDENTIFIERS ON,从技术上讲,你应该使用quotes而不是square brackets标识符:
T-SQL(不好?) (例如,由Entity Framework生成的SQL)
UPDATE [dbo].[Customers]
SET [FirstName] = N'Ian'
WHERE [CustomerID] = 7
Run Code Online (Sandbox Code Playgroud)
ANSI-SQL(好吗?)
UPDATE "dbo"."Customers"
SET "FirstName" = N'Ian'
WHERE "CustomerID" = 7
Run Code Online (Sandbox Code Playgroud)
我认为在重建索引时它已被关闭.
在处理过滤索引时,您需要打开以下设置:
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
SET ARITHABORT ON
SET CONCAT_NULL_YIELDS_NULL ON
SET QUOTED_IDENTIFIER ON
Run Code Online (Sandbox Code Playgroud)
您需要添加添加
SET ANSI_NULLS, QUOTED_IDENTIFIER ON
Run Code Online (Sandbox Code Playgroud)
对于我的所有存储过程编辑具有计算列的表以避免该错误.
当SET ANSI_NULLS为ON时,即使column_name中存在空值,使用WHERE column_name = NULL的SELECT语句也会返回零行.使用WHERE column_name <> NULL的SELECT语句返回零行,即使column_name中存在非空值也是如此.
当SET ANSI_NULLS为OFF时,Equals(=)和Not Equal To(<>)比较运算符不遵循ISO标准.使用WHERE column_name = NULL的SELECT语句将返回column_name中具有空值的行.使用WHERE column_name <> NULL的SELECT语句将返回列中具有非空值的行.此外,使用WHERE column_name <> XYZ_value的SELECT语句将返回非XYZ_value且不为NULL的所有行.
当SET QUOTED_IDENTIFIER为ON时,标识符可以用双引号分隔,文字必须用单引号分隔.当SET QUOTED_IDENTIFIER为OFF时,不能引用标识符,并且必须遵循标识符的所有Transact-SQL规则.有关更多信息,请参阅数据库标识符.文字可以用单引号或双引号分隔.
当SET QUOTED_IDENTIFIER为ON(默认)时,由双引号分隔的所有字符串都将被解释为对象标识符.因此,带引号的标识符不必遵循标识符的Transact-SQL规则.它们可以是保留关键字,可以包含Transact-SQL标识符中通常不允许的字符.双引号不能用于分隔文字字符串表达式; 必须使用单引号括起文字字符串.如果单个引号(')是文字字符串的一部分,则它可以用两个单引号(")表示.当保留关键字用于数据库中的对象名称时,SET QUOTED_IDENTIFIER必须为ON.
当SET CONCAT_NULL_YIELDS_NULL为ON时,将空值与字符串连接会产生NULL结果.例如,SELECT'abc'+ NULL产生NULL.当SET CONCAT_NULL_YIELDS_NULL为OFF时,将空值与字符串连接将产生字符串本身(空值被视为空字符串).例如,SELECT'abc'+ NULL产生abc.
如果未指定SET CONCAT_NULL_YIELDS_NULL,则应用CONCAT_NULL_YIELDS_NULL数据库选项的设置.