NOTE: I checked Understanding QUOTED_IDENTIFIER and it does not answer my question.
I got my DBAs to run an index I made on my Prod servers (they looked it over and approved it).
It sped up my queries just like I wanted. However, I started getting errors like this:
As a developer I have usually ignored these settings. And it has never mattered. (For 9+ years). Well, today it matters.
I went and looked at one of the sprocs that are failing and it has this before the create for the sproc:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Can anyone tell me from a application developer point of view what these set statements do? (Just adding the above code before my index create statements did not fix the problem.)
NOTE: Here is an example of what my indexes looked like:
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
4条答案
按热度按时间c86crjj01#
OK, from an application developer's point of view, here's what these settings do:
QUOTED_IDENTIFIER
This setting controls how quotation marks
".."
are interpreted by the SQL compiler. WhenQUOTED_IDENTIFIER
is ON then quotes are treated like brackets ([...]
) and can be used to quote SQL object names like table names, column names, etc. When it is OFF (not recommended), then quotes are treated like apostrophes ('..'
) and can be used to quote text strings in SQL commands.ANSI_NULLS
This setting controls what happens when you try to use any comparison operator other than
IS
on NULL. When it is ON, these comparisons follow the standard which says that comparing to NULL always fails (because it isn't a value, it's a Flag) and returnsFALSE
. When this setting is OFF (really not recommended) you can sucessfully treat it like a value and use=
,<>
, etc. on it and get back TRUE as appropiate.The proper way to handle this is to instead use the
IS
(ColumnValue IS NULL ..
).CONCAT_NULL_YIELDS_NULL
This setting controls whether NULLs "Propogate" whn used in string expressions. When this setting is ON, it follows the standard and an expression like
'some string' + NULL ..
always returns NULL. Thus, in a series of string concatenations, one NULL can cause the whole expression to return NULL. Turning this OFF (also, not recommended) will cause the NULLs to be treated like empty strings instead, so'some string' + NULL
just evaluates to'some string'
.The proper way to handle this is with the COALESCE (or ISNULL) function:
'some string' + COALESCE(NULL, '') ..
.nafvub8i2#
I find the documentation , blog posts , Stackoverflow answers unhelpful in explaining what turning on
QUOTED_IDENTIFIER
means.Olden times
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 to name a table, view, stored 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 they had other ideas:
'...'
) for strings"..."
)Which 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 if it were T-SQL, it is nonsense:
and SQL Server tells you so:
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*(aka SET QUOTED_IDENTIFIER OFF)*
SET QUOTED_IDENTIFIER ON
These days everyone has
SET QUOTED_IDENTIFIERS ON
, which technically means you should be usingquotes
rather thansquare brackets
around identifiers:T-SQL (bad?)(e.g. SQL generated by Entity Framework)
ANSI-SQL (good?)
In reality nobody in the SQL Server universe uses U+0022 QUOTATION MARK " to wrap identifiers. We all continue to use [].
wgx48brx3#
I think while rebuilding the indexes it got turned off.
Do check the SET Options with their setting values required while working with filtered index
You need to turn On the below setting while dealing with filtered index:
You need add to add
for all my stored procedures editing a table with a computed column to avoid that error.
ANSI_NULLS:
When SET ANSI_NULLS is ON, a SELECT statement that uses WHERE column_name = NULL returns zero rows even if there are null values in column_name. A SELECT statement that uses WHERE column_name <> NULL returns zero rows even if there are nonnull values in column_name.
When SET ANSI_NULLS is OFF, the Equals (=) and Not Equal To (<>) comparison operators do not follow the ISO standard. A SELECT statement that uses WHERE column_name = NULL returns the rows that have null values in column_name. A SELECT statement that uses WHERE column_name <> NULL returns the rows that have nonnull values in the column. Also, a SELECT statement that uses WHERE column_name <> XYZ_value returns all rows that are not XYZ_value and that are not NULL.
QUOTED_IDENTIFIER
When SET QUOTED_IDENTIFIER is ON, identifiers can be delimited by double quotation marks, and literals must be delimited by single quotation marks. When SET QUOTED_IDENTIFIER is OFF, identifiers cannot be quoted and must follow all Transact-SQL rules for identifiers. For more information, see Database Identifiers. Literals can be delimited by either single or double quotation marks.
When SET QUOTED_IDENTIFIER is ON (default), all strings delimited by double quotation marks are interpreted as object identifiers. Therefore, quoted identifiers do not have to follow the Transact-SQL rules for identifiers. They can be reserved keywords and can include characters not generally allowed in Transact-SQL identifiers. Double quotation marks cannot be used to delimit literal string expressions; single quotation marks must be used to enclose literal strings. If a single quotation mark (') is part of the literal string, it can be represented by two single quotation marks ("). SET QUOTED_IDENTIFIER must be ON when reserved keywords are used for object names in the database.
CONCAT_NULL_YIELDS_NULL
When SET CONCAT_NULL_YIELDS_NULL is ON, concatenating a null value with a string yields a NULL result. For example, SELECT 'abc' + NULL yields NULL. When SET CONCAT_NULL_YIELDS_NULL is OFF, concatenating a null value with a string yields the string itself (the null value is treated as an empty string). For example, SELECT 'abc' + NULL yields abc.
If SET CONCAT_NULL_YIELDS_NULL is not specified, the setting of the CONCAT_NULL_YIELDS_NULL database option applies.
0qx6xfy64#
ANSI_NULLS ON makes any binary boolean expression with a null value evaluate to false. Using the following template:
The proper way to test for null is to use
is [not] NULL
QUOTED_IDENTIFER ON merely allows you to use double quotes to delimit identifiers (bad idea IMO, just user square brackets)