注意:我检查了Understanding QUOTED_IDENTIFIER但它没有回答我的问题。
我让我的DBA运行我在Prod服务器上制作的索引(他们查看并批准了它)。
它加快了我的疑问,就像我想要的那样。但是,我开始遇到这样的错误:
作为开发人员,我通常会忽略这些设置。它从来都不重要。 (9年以上)。好吧,今天很重要。
我去看了一个失败的sprocs,它在创建sproc之前有这个:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
有人能从应用程序开发人员的角度告诉我这些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
答案 0 :(得分:51)
好的,从应用程序开发人员的角度来看,以下是这些设置的作用:
此设置控制SQL编译器如何解释引号".."
。当QUOTED_IDENTIFIER
为ON时,引号被视为括号([...]
),可用于引用SQL对象名称,如表名,列名等。当它为OFF(不推荐)时,则引号被视为撇号('..'
),可用于在SQL命令中引用文本字符串。
此设置控制当您尝试在NULL上使用IS
以外的任何比较运算符时发生的情况。当它为ON时,这些比较遵循标准,该标准表示与NULL相比总是失败(因为它不是值,它是标志)并返回FALSE
。当此设置为OFF(确实 不 推荐)时,您可以成功将其视为值,并使用=
,<>
等对其进行处理并且在适当的时候返回TRUE。
处理此问题的正确方法是使用IS
(ColumnValue IS NULL ..
)。
此设置控制是否在字符串表达式中使用NULL“Propogate”。当此设置为ON时,它遵循标准,并且类似'some string' + NULL ..
的表达式始终返回NULL。因此,在一系列字符串连接中,一个NULL可以导致整个表达式返回NULL。将其设置为OFF(也不建议使用)将导致将NULL视为空字符串,因此'some string' + NULL
仅计算为'some string'
。
处理此问题的正确方法是使用COALESCE(或ISNULL)函数:'some string' + COALESCE(NULL, '') ..
。
答案 1 :(得分:11)
我发现the documentation,blog posts,Stackoverflow answers无法解释启用QUOTED_IDENTIFIER
的含义。
最初,SQL Server允许您在字符串之间交替使用引号("..."
)和撇号('...'
)(就像Javascript一样) ):
SELECT "Hello, world!"
- 引号 SELECT 'Hello, world!'
- 撇号 如果你想要一个名称表,视图,程序,列等,否则会违反所有命名对象的规则,你可以将它包装在方括号中([
,]
):
CREATE TABLE [The world's most awful table name] (
[Hello, world!] int
)
SELECT [Hello, world!] FROM [The world's most awful table name]
这一切都有效,并且有意义。
然后ANSI出现并有其他想法:
"..."
)'...'
)作为字符串这意味着,如果您想&#34;引用&#34; 时髦的列或表名,您必须使用引号:
SELECT "Hello, world!" FROM "The world's most awful table name"
如果您了解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'.
因此,Microsoft添加了一项功能,让您选择加入ANSI的ANSI风格。
<强>原始强>
SELECT "Hello, world!" --valid
SELECT 'Hello, world!' --valid
SET QUOTED_IDENTIFIER ON
SELECT "Hello, world!" --INVALID
SELECT 'Hello, world!' --valid
现在每个人都有SET QUOTED_IDENTIFIERS ON
,这在技术上意味着您应该使用quotes
而不是square brackets
标识符:
T-SQL(不好?) (例如,实体框架生成的SQL)
UPDATE [dbo].[Customers]
SET [FirstName] = N'Ian'
WHERE [CustomerID] = 7
ANSI-SQL(好吗?)
UPDATE "dbo"."Customers"
SET "FirstName" = N'Ian'
WHERE "CustomerID" = 7
答案 2 :(得分:5)
我认为在重建索引时它会被关闭。
请检查 SET Options with their setting values required while working with filtered index
在处理过滤索引时,您需要打开以下设置:
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
您需要添加添加
SET ANSI_NULLS, QUOTED_IDENTIFIER ON
用于编辑具有计算列的表的所有存储过程以避免该错误。
<强> ANSI_NULLS: 强>
当SET ANSI_NULLS为ON时,使用WHERE的SELECT语句 column_name = NULL即使存在空值,也返回零行 列名。使用WHERE column_name&lt;&gt;的SELECT语句空值 即使column_name中存在非空值,也会返回零行。
当SET ANSI_NULLS为OFF时,等于(=)和不等于(&lt;&gt;) 比较运算符不符合ISO标准。一个选择 使用WHERE column_name = NULL的语句返回的行 在column_name中具有空值。使用WHERE的SELECT语句 column_name&lt;&gt; NULL返回具有非空值的行 柱。此外,使用WHERE column_name&lt;&gt;的SELECT语句 XYZ_value返回非XYZ_value且不是XYZ_value的所有行 NULL。
<强> QUOTED_IDENTIFIER 强>
当SET QUOTED_IDENTIFIER为ON时,标识符可以由分隔符组成 双引号,文字必须用单个分隔 引号。当SET QUOTED_IDENTIFIER为OFF时,标识符不能 引用并且必须遵循标识符的所有Transact-SQL规则。对于 更多信息,请参阅数据库标识符。文字可以分隔 用单引号或双引号。
当SET QUOTED_IDENTIFIER为ON(默认值)时,所有字符串都由 双引号被解释为对象标识符。 因此,带引号的标识符不必遵循Transact-SQL 标识符规则。它们可以是保留关键字,也可以包含 Transact-SQL标识符中通常不允许使用的字符。双 引号不能用于分隔文字字符串表达式; 必须使用单引号括起文字字符串。如果一个 单引号(')是文字字符串的一部分,它可以是 用两个单引号(“)表示.SET QUOTED_IDENTIFIER 当保留关键字用于对象名称时,必须为ON 数据库中。
<强> CONCAT_NULL_YIELDS_NULL 强>
当SET CONCAT_NULL_YIELDS_NULL为ON时,连接空值 用字符串产生NULL结果。例如,SELECT'abc'+ NULL 产生NULL。当SET CONCAT_NULL_YIELDS_NULL为OFF时,连接a 带字符串的null值产生字符串本身(空值为 被视为空字符串)。例如,SELECT'abc'+ NULL产生 ABC
如果未指定SET CONCAT_NULL_YIELDS_NULL,则设置为 CONCAT_NULL_YIELDS_NULL数据库选项适用。
答案 3 :(得分:1)
ANSI_NULLS ON使任何具有空值的二进制布尔表达式求值为false。使用以下模板:
declare @varA, @varB int
if <binary boolean expression>
begin
print 'true'
end
else
begin
print 'false'
end
@varA: NULL; @varB: NULL; @varA = @varB evaluates to false
@varA: 1; @varB: NULL; @varA <> @varB evaluates to false
测试null的正确方法是使用is [not] NULL
@varA: NULL; @varA is NULL evaluates to true
@varA: 1; @varA is not NULL evaluates to true
QUOTED_IDENTIFER ON仅允许您使用双引号来分隔标识符(坏主意IMO,只是用户方括号)
from tblA "a" -- ok when ON, not ok when OFF
from tblA [a] -- always ok