ANSI NULLS и QUOTED IDENTIFIER убивали вещи. Для чего они?

примечание: Я проверил понимание значение параметра и это не ответ на мой вопрос.

Я получил мои DBAs для запуска индекса, который я сделал на моих серверах Prod (они просмотрели его и одобрили).

это ускорило мои запросы, как я и хотел. Однако я начал получать такие ошибки:

UPDATE failed because the following SET options have incorrect settings: ANSI_NULL, QUOTED_IDENTIFIER, CONCAT_NULL_YIELDS_NUL

как разработчик я обычно игнорировал эти настройки. И это никогда не имело значения. (За 9+ лет). Ну, сегодня это важно.

Я пошел и посмотрел на один из sprocs, которые терпят неудачу, и у него есть это перед созданием для sproc:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

может ли кто-нибудь сказать мне с точки зрения разработчика приложений, что делают эти операторы set? (просто добавление вышеуказанного кода перед моими инструкциями Index create не устранило проблему.)

Примечание: вот пример того, как выглядели мои индексы:

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 ответов


OK, с точки зрения разработчика приложений, вот что делают эти настройки:

значение параметра

этот параметр управляет тем, как кавычки ".." интерпретируются компилятором SQL. Когда QUOTED_IDENTIFIER включено, тогда кавычки рассматриваются как скобки ([...]) и может использоваться для цитирования имен объектов SQL, таких как имена таблиц, имена столбцов и т. д. Когда он выключен (не рекомендуется), кавычки обрабатываются как апострофы ('..') и может использоваться для цитаты текстовые строки в командах SQL.

параметр ansi_nulls

этот параметр управляет тем, что происходит при попытке использовать любой оператор сравнения, кроме IS on NULL. Когда он включен, эти сравнения следуют стандарту, который говорит, что сравнение с NULL всегда терпит неудачу (потому что это не значение, Это флаг) и возвращает FALSE. Когда этот параметр выключен (действительно не рекомендуется) вы можете успешно рассматривать его как значение и использовать =, <>, etc. на нем и вернись как можно скорее.

правильный способ справиться с этим-это использовать IS (ColumnValue IS NULL ..).

параметр concat_null_yields_null

этот параметр определяет, будут ли NULLs "Propogate" whn использоваться в строковых выражениях. Когда этот параметр включен, он следует стандарту и выражению типа 'some string' + NULL .. всегда возвращает NULL. Таким образом, в серии конкатенаций строк один NULL может привести к возвращению всего выражения NULL. Отключение этого (также не рекомендуется) приведет к тому, что нули будут рассматриваться как пустые строки, поэтому 'some string' + NULL просто оценивает в 'some string'.

правильный способ справиться с этим - с помощью функции COALESCE (или ISNULL):'some string' + COALESCE(NULL, '') ...


найти документация, блога, и StackOverflow ответы бесполезно объяснять, что включается QUOTED_IDENTIFIER средства.

былые времена

первоначально SQL Server разрешал использовать кавычки ("...") и Апостроф ('...') вокруг строк взаимозаменяемо (как это делает Javascript):

  • SELECT "Hello, world!" --цитата Марк!--38-->
  • 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

затем Анси и другие идеи:

  • если у вас есть фанк имя, оберните его в кавычки ("...")
  • использовать Апостроф ('...') для строк
  • и мы даже не заботимся о ваших квадратных скобках

что означает, что если вы хотите "цитата" фанки имя столбца или таблицы вы должны использовать кавычки:

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

если вы знали SQL Server, вы знали, что цитата Маркс!--31--> уже использовались для представления строк. Если вы слепо пытались выполнить это В ANSI-SQL В как будто T-SQL: это ерунда, и SQL Server сказал вам так:

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

вы должны выбрать новое поведение ANSI

таким образом, Microsoft добавила функцию, чтобы позволить вам выбрать в ANSI вкус SQL.

Оригинал

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

УСТАНОВИТЬ QUOTED_IDENTIFIER ON

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

в наши дни у всех есть SET QUOTED_IDENTIFIERS ON, который технически означает, что вы должны использовать quotes, а не square brackets вокруг идентификаторов:

T-SQL (плохо?) (например, SQL, созданный Entity Framework)

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

ANSI-SQL (хорошо?)

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

Я думаю, что при перестройке индексов он был выключен.

проверьте установите параметры с их значениями настроек, требуемыми при работе с фильтрованным индексом

при работе с фильтрованным индексом необходимо включить нижеприведенную настройку:

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 включен, оператор SELECT, который использует WHERE column_name = NULL возвращает нулевые строки, даже если в имя столбца. Инструкция SELECT, использующая WHERE column_name NULL возвращает нулевые строки, даже если в column_name есть значения nonnull.

когда SET ANSI_NULLS выключен, равно ( = ) и не равно () операторы сравнения не следуют стандарт ISO. ОТБОР оператор, использующий WHERE column_name = NULL возвращает строки, которые имеют значения null в column_name. Инструкция SELECT, использующая WHERE column_name NULL возвращает строки, которые имеют значения nonnull в колонна. Кроме того, оператор SELECT, который использует WHERE column_name Возвращает XYZ_value всех строк, которые не XYZ_value и что не НОЛЬ.

значение параметра

при установке QUOTED_IDENTIFIER включен, идентификаторы могут быть разделены двойные кавычки, и литералы должны быть заключены в одинарные кавычки. Когда SET QUOTED_IDENTIFIER выключен, идентификаторы не могут быть в кавычках и должен следовать всем правилам Transact-SQL для идентификаторов. Для дополнительные сведения см. В разделе идентификаторы базы данных. Литералы могут быть разделены одинарными или двойными кавычками.

когда SET QUOTED_IDENTIFIER включен (по умолчанию), все строки разделены двойная цитата метки интерпретируются как идентификаторы объектов. Таким образом кавычки идентификаторы не должны следовать Transact-SQL правила для идентификаторов. Они могут быть зарезервированы ключевые слова и могут включать символы, не разрешенные в языке Transact-SQL для идентификаторов. Двойной кавычки нельзя использовать для разграничения строковых выражений; одинарные кавычки должны использоваться для заключения символьных строк. Если одинарная кавычка ( ' ) является частью литеральной строки, она может быть представлены два один кавычки.)"( УСТАНОВИТЬ ЗНАЧЕНИЕ ПАРАМЕТРА должен быть включен, когда зарезервированные ключевые слова используются для имен объектов в база данных.

параметр concat_null_yields_null

когда SET CONCAT_NULL_YIELDS_NULL включен, объединение нулевого значения с помощью строки получается нулевой результат. Например, выберите ' abc ' + NULL дает NULL. Когда SET CONCAT_NULL_YIELDS_NULL выключен, объединение значения null со строкой дает саму строку (значение null обрабатывается как пустая строка). Например, выберите " abc " + null выходы азбука.

Если SET CONCAT_NULL_YIELDS_NULL не указан, то настройка Применяется параметр базы данных CONCAT_NULL_YIELDS_NULL.


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