Разница между не в и с нулевыми значениями - PullRequest
0 голосов
/ 31 августа 2018

Я наткнулся на какой-то старый код в нашей БД, который вел себя не так, как ожидалось. Мне удалось сузить его до значения NULL для предложения IN.

Я вывел тест, который демонстрирует это:

declare @test   nvarchar(50) = '8620M/9010';
declare @testLT nvarchar(50) = '8004/9010';
declare @testLV nvarchar(50) =  null;  --'asd'
select case when @test not in (@testLT, @testLV) then 1 else 0 end

Если testLV равен нулю, NOT IN возвращает тот же результат, что и предложение IN.

Я хочу понять механизм, стоящий за этим поведением. Может кто-нибудь объяснить?

Ps. Я, вероятно, заменит его на EXCEPT пункт

Ответы [ 4 ]

0 голосов
/ 31 августа 2018

Из документации :

Внимание

Любые нулевые значения, возвращаемые подзапросом или выражением, которые сравниваются с test_expression. использование IN или NOT IN возвращает НЕИЗВЕСТНО. Использование нулевых значений вместе с IN или NOT IN может привести к неожиданным результатам.

Сравнение между @test и @testLV всегда будет возвращать "НЕИЗВЕСТНО" вместо ИСТИНА или ЛОЖЬ.

0 голосов
/ 31 августа 2018

NULL означает, что я не знаю, что является значением отсутствия.

В вашем случае IN будет переводиться на

@test = @testLT or @test =@testLV

В вашем случае NOT IN будет переводиться на

@test <> @testLT or @test <> @testLV

Но NULL не может использовать <> или = для получения значения, когда ANSI_NULLS установлено ON.

0 голосов
/ 31 августа 2018

На семантику NOT IN влияет значение NULL в списке. В SQL NULL означает «Я не знаю значения; это может быть что угодно».

Итак, если вы сделаете:

where 1 in (1, 2)

тогда возвращается true.

where 1 in (3, 4)

возвращает false.

Пока все хорошо. Теперь рассмотрим:

where 1 not in (1, 2, NULL)

Ну, "1" явно в списке. Так что это возвращает ложь.

where 1 not in (3, 4, NULL)

Ну, «1» - это не «3» или «4». Но это NULL? Мы не знаем Таким образом, это возвращает NULL, а не истина. И NULL обрабатывается так же, как и ложь в условии WHERE, что означает, что строка отфильтрована. (Как примечание: check условия ведут себя по-разному, только явное ложь не дает check.)

Итак, ничего не возвращается с NOT IN, если любое из значений NULL.

Эта ситуация почти всегда возникает в контексте подзапросов (а не констант). По этой причине я рекомендую использовать NOT EXISTS вместо NOT IN во всех случаях с подзапросом.

0 голосов
/ 31 августа 2018

IN

Внимание

Любые нулевые значения, возвращаемые подзапросом или выражением, которые сравниваются для test_expression, используя IN или NOT IN, возвращаем UNKNOWN. Используя нуль значения вместе с IN или NOT IN могут привести к неожиданным результатам.

НЕИЗВЕСТНО <> ИСТИНА

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...