Что означает «SET ANSI_NULLS ON» в SQL Server?


92

В определении говорится:

Когда для SET ANSI_NULLS установлено значение ON, инструкция SELECT, использующая WHERE column_name = NULL, возвращает нулевые строки, даже если в столбце имя_столбца есть нулевые значения. Оператор SELECT, использующий WHERE column_name <> NULL, возвращает нулевые строки, даже если в column_name есть ненулевые значения.

Означает ли это, что в этот запрос не будут включены нули?

SELECT Region
FROM employees
WHERE Region = @region

Или это ANSI_NULLкасается только таких запросов (где WHEREесть конкретное слово NULL)?

SELECT Region
FROM employees
WHERE Region = NULL

1
Нет ли ответа в 4-м параграфе официальной документации, из которой вы скопировали 1-й параграф, а именно: -> «SET ANSI_NULLS ON влияет на сравнение только в том случае, если один из операндов сравнения является переменной, имеющей значение NULL. или буквальный NULL. Если обе стороны сравнения являются столбцами или составными выражениями, параметр не влияет на сравнение ».
— user1451111

Ответы:


68

Это означает , что ни одна строка не будет возвращена , если @regionесть NULL, при использовании в первом примере, даже если есть строки в таблице , где RegionнаходитсяNULL .

Когда ANSI_NULLSон включен (который вы всегда должны устанавливать в любом случае, так как опция, чтобы не включать его, будет удалена в будущем), любая операция сравнения, в которой (по крайней мере) один из операндов, NULLдает третье логическое значение - UNKNOWN( в отличие от TRUEи FALSE).

UNKNOWNзначения распространяются через любые комбинирующие логические операторы, если они еще не определены (например, ANDс FALSEоперандом или ORс TRUEоперандом) или отрицаниями ( NOT).

Предложение WHEREиспользуется для фильтрации набора результатов, созданного FROMпредложением, так что общее значение WHEREпредложения должно быть TRUEтаким, чтобы строка не фильтровалась. Таким образом, если в UNKNOWNрезультате какого-либо сравнения будет получено an, строка будет отфильтрована.


@ user1227804 в ответ включает эту цитату:

Если обе стороны сравнения - столбцы или составные выражения, параметр не влияет на сравнение.

от *SET ANSI_NULLS

Однако я не уверен, какой смысл он пытается донести, поскольку при NULLсравнении двух столбцов (например, в a JOIN) сравнение все равно не выполняется:

create table #T1 (
    ID int not null,
    Val1 varchar(10) null
)
insert into #T1(ID,Val1) select 1,null

create table #T2 (
    ID int not null,
    Val1 varchar(10) null
)
insert into #T2(ID,Val1) select 1,null

select * from #T1 t1 inner join #T2 t2 on t1.ID = t2.ID and t1.Val1 = t2.Val1

Вышеупомянутый запрос возвращает 0 строк, тогда как:

select * from #T1 t1 inner join #T2 t2 on t1.ID = t2.ID and (t1.Val1 = t2.Val1 or t1.Val1 is null and t2.Val1 is null)

Возвращает одну строку. Таким образом, даже если оба операнда являются столбцами, NULLне равно NULL. А в документации по= операндам ничего не говорится:

Когда вы сравниваете два NULLвыражения, результат зависит от ANSI_NULLSнастройки:

Если ANSI_NULLSустановлено значение ON, результатом будет NULL1 , в соответствии с соглашением ANSI о том, что NULL(или неизвестное) значение не равно другому NULLили неизвестному значению.

Если ANSI_NULLSустановлено значение OFF, результат NULLсравнения с NULLравен TRUE.

Сравнение NULLс не- NULLзначением всегда приводит к FALSE2 .

Однако и 1, и 2 неверны - результат обоих сравнений UNKNOWN.


* Загадочный смысл этого текста был наконец открыт много лет спустя. На самом деле это означает, что для этих сравнений параметр не имеет никакого эффекта и всегда действует так, как если бы параметр был включен . Было бы яснее, если бы было указано, что SET ANSI_NULLS OFFэто настройка, которая не имеет никакого влияния.


1
так что, если я правильно вас понял: это влияет и на результат фразы «Где регион = @region», а не только тогда, когда я пишу конкретно «Где регион = null»?
— Rodniko

7

Если @Regionне является nullзначением (допустим @Region = 'South'), он не будет возвращать строки, в которых поле «Регион» имеет значение NULL, независимо от значения ANSI_NULLS.

ANSI_NULLS будет иметь значение только тогда, когда значение @Regionравно null, то есть когда ваш первый запрос по существу становится вторым.

В этом случае ANSI_NULLS ON не будет возвращать никаких строк (потому null = nullчто даст неизвестное логическое значение (aka null)), а ANSI_NULLS OFF вернет любые строки, в которых поле Region имеет значение NULL (потому что null = nullбудет давать true)


6

Если для ANSI_NULLS установлено значение «ON», и если мы применим =, <> к значению столбца NULL при записи оператора select, то он не вернет никакого результата.

пример

create table #tempTable (sn int, ename varchar(50))

insert into #tempTable
values (1, 'Manoj'), (2, 'Pankaj'), (3, NULL), (4, 'Lokesh'), (5, 'Gopal')

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

select * from #tempTable where ename is NULL -- (1 row(s) affected)
select * from #tempTable where ename = NULL -- (0 row(s) affected)
select * from #tempTable where ename is not NULL -- (4 row(s) affected)
select * from #tempTable where ename <> NULL -- (0 row(s) affected)

ВЫКЛЮЧИТЬ ANSI_NULLS

select * from #tempTable where ename is NULL -- (1 row(s) affected)
select * from #tempTable where ename = NULL -- (1 row(s) affected)
select * from #tempTable where ename is not NULL -- (4 row(s) affected)
select * from #tempTable where ename <> NULL -- (4 row(s) affected)

2
+1 за ЕДИНСТВЕННЫЙ ответ, который четко различает WHERE X IS NULLи WHERE X = NULL, и как ANSI_NULLS влияет на результат. Несмотря на излишне рьяные попытки оппонентов, ЭТО должен быть принятым ответом!
— Riegardt Steyn 08

1
+1 за объяснение с использованием примеров, которые всегда будут более ясными и краткими, а не длинными предложениями.
— peter.aryanto

3

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

IT возвращает все значения, включая нулевые значения в таблице

ВЫКЛЮЧИТЬ ANSI_NULLS

Заканчивается, когда столбцы содержат нулевые значения


2
Что еще этот ответ добавляет к уже указанным ответам? С осторожностью добавляйте новые ответы на старые вопросы - они должны содержать расширенное объяснение уже опубликованных решений или предоставлять новое понимание - Из обзора
— Takarii

1

Думаю, здесь главное:

Никогда не пользователь:

  • @anything = NULL
  • @anything <> NULL
  • @anything != null

Всегда используйте:

  • @anything IS NULL
  • @anything IS NOT NULL

0

Если установить ANSI NULLS OFF, сравнение NULL = NULL вернет истинное значение. Например:

        SET ANSI_NULLS OFF
        select * from sys.tables
        where principal_id = Null

вернет результат, как показано ниже: zcwInvoiceDeliveryType 744547 NULL zcExpenseRptStatusTrack 2099048 NULL ZCVendorPermissions 2840564 NULL ZCWOrgLevelClientFee 4322525 NULL

Пока этот запрос не вернет никаких результатов:

        SET ANSI_NULLS ON 
        select * from sys.tables
        where principal_id = Null

0

https://docs.microsoft.com/en-us/sql/t-sql/statements/set-ansi-nulls-transact-sql

Когда для SET ANSI_NULLS установлено значение ON, инструкция SELECT, использующая WHERE column_name = NULL, возвращает нулевые строки, даже если в столбце имя_столбца есть нулевые значения. Оператор SELECT, использующий WHERE column_name <> NULL, возвращает нулевые строки, даже если в column_name есть ненулевые значения.

Например,

DECLARE @TempVariable VARCHAR(10)
SET @TempVariable = NULL

SET ANSI_NULLS ON
SELECT 'NO ROWS IF SET ANSI_NULLS ON' where    @TempVariable = NULL
-- IF ANSI_NULLS ON , RETURNS ZERO ROWS


SET ANSI_NULLS OFF
SELECT 'THERE WILL BE A ROW IF ANSI_NULLS OFF' where    @TempVariable =NULL
-- IF ANSI_NULLS OFF , THERE WILL BE ROW !
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.