Странное поведение SQL, мне интересно, почему это работает так, как работает - PullRequest
2 голосов
/ 25 марта 2010

Рассмотрим следующий Transact sql.

DECLARE @table TABLE(val VARCHAR(255) NULL)

INSERT INTO @table (val) VALUES('a')
INSERT INTO @table (val) VALUES('b')
INSERT INTO @table (val) VALUES('c')
INSERT INTO @table (val) VALUES('d')
INSERT INTO @table (val) VALUES(NULL)

select val 
from @table
where val not in ('a') 

Я ожидаю, что это вернется

b, c, d, NULL

но вместо этого он возвращает

b, c, d

Почему это так? NULL не оценивается? NULL как-то в наборе 'a'?

Ответы [ 5 ]

3 голосов
/ 25 марта 2010

Ответ

По умолчанию NULL для SQL означает «неизвестно». Таким образом, любое сравнение с «неизвестным» является «неизвестным».

Например, если рядом с Бобом стоит незнакомец, и вы хотите задать вопрос: «Имя незнакомца совпадает с именем Боба?». Ответ неизвестен.

Поскольку вы спрашиваете: «Верните все записи, где значение не равно« A »». Когда он попадает в этот столбец NULL, SQL по-прежнему говорит: «Я не знаю». Поскольку выражение не имеет значения true, эта запись не возвращается.

Решение

Любое выражение, которое сравнивает NULL с константой, всегда будет NULL, поэтому используйте специальные IS NULL и IS NOT NULL для проверки значений NULL.

Это даст вам b, c, d и NULL:

SELECT val 
FROM @table
WHERE val NOT IN ('a') OR val IS NULL

Обходной путь

Вы можете изменить поведение по умолчанию для NULL:

SET ANSI_NULLS OFF
3 голосов
/ 25 марта 2010

, чтобы получить нулевую строку, попробуйте:

select val 
from @table
where val not in ('a') OR val IS NULL

попробуйте это:

select 1 where null in (null)
select 1 where null in (1)
select 1 where 1 in (null)

все возвращаемые нулевые строки

null = null всегда false и null = anythng всегда false , при проверке строки NULL предложение WHERE равно WHERE NULL в ('a') всегда ложь.

2 голосов
/ 25 марта 2010

Вы не можете сделать равенство с NULL таким образом.

Учитывайте это

select case when 'a' = NULL then 1 else 0 end
select case when 'a' <> NULL then 1 else 0 end

Для выше вы получите

result
------
  0
  0

Для вашего запроса попробуйте

 where isnull(val,'') not in ('a') 
2 голосов
/ 25 марта 2010

Попробуйте, и вы получите другой ответ:

set ansi_nulls off;
DECLARE @table TABLE(val VARCHAR(255) NULL)

INSERT INTO @table (val) VALUES('a')
INSERT INTO @table (val) VALUES('b')
INSERT INTO @table (val) VALUES('c')
INSERT INTO @table (val) VALUES('d')
INSERT INTO @table (val) VALUES(NULL)

select val 
from @table
where val not in ('a')

У вас есть ansi_nulls, поэтому он обрабатывает нули соответственно.

2 голосов
/ 25 марта 2010

Нуль нельзя сравнивать напрямую ни с чем.

попробовать

select val  
from @table 
where coalesce(val, '') not in ('a')  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...