ANSI_NULLS and QUOTED_IDENTIFIER killed things. What are they for?

后端 未结 4 549
北海茫月
北海茫月 2020-12-24 02:43

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

相关标签:
4条回答
  • 2020-12-24 02:57

    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:

    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
    

    You need add to add

    SET ANSI_NULLS, QUOTED_IDENTIFIER ON
    

    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.

    0 讨论(0)
  • 2020-12-24 03:00

    ANSI_NULLS ON makes any binary boolean expression with a null value evaluate to false. Using the following template:

    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
    

    The proper way to test for null is to use is [not] NULL

    @varA: NULL; @varA is NULL evaluates to true
    @varA: 1; @varA is not NULL evaluates to true
    

    QUOTED_IDENTIFER ON merely allows you to use double quotes to delimit identifiers (bad idea IMO, just user square brackets)

    from tblA "a" -- ok when ON, not ok when OFF
    from tblA [a] -- always ok
    
    0 讨论(0)
  • 2020-12-24 03:05

    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 mark
    • SELECT 'Hello, world!' --apostrophe

    And 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 ([, ]):

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

    And that all worked, and made sense.

    Then came ANSI

    Then ANSI came along and had other ideas:

    • if you have a funky name, wrap it in quotation marks ("...")
    • use apostrophe ('...') for strings
    • and we don't even care about your square brackets

    Which means that if you wanted to "quote" a funky column or table name you must use quotation marks:

    SELECT "Hello, world!" FROM "The world's most awful table name"
    

    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, it is the same as trying to execute:

    SELECT 'Hello, world!' FROM 'The world''s most awful table name'
    

    as though it were T-SQL: it's nonsense, and SQL Server tells you so:

    Msg 102, Level 15, State 1, Line 8
    Incorrect syntax near 'The world's most awful table name'.
    

    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)

    SELECT "Hello, world!" --valid
    SELECT 'Hello, world!' --valid
    

    SET QUOTED_IDENTIFIER ON

    SELECT "Hello, world!" --INVALID
    SELECT 'Hello, world!' --valid
    

    These days everyone has SET QUOTED_IDENTIFIERS ON, which technically means you should be using quotes rather than square brackets around identifiers:

    T-SQL (bad?) (e.g. SQL generated by Entity Framework)

    UPDATE [dbo].[Customers]
    SET [FirstName] = N'Ian'
    WHERE [CustomerID] = 7
    

    ANSI-SQL (good?)

    UPDATE "dbo"."Customers"
    SET "FirstName" = N'Ian'
    WHERE "CustomerID" = 7
    
    0 讨论(0)
  • 2020-12-24 03:11

    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. When QUOTED_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 returns FALSE. 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, '') ...

    0 讨论(0)
提交回复
热议问题