Сервер Sql: оператор CASE делает неожиданное поведение при сравнении с NULL
Данный:
Следующий оператор Select:
select case NULL when NULL then 0 else 1 end
Проблема:
- Почему ExecuteScalar () возвращает null, когда мои возвращаемые значения не равны нулю?
- Подсчет нулевых значений при подключении в T-SQL
- УДАЛЕНИЕ ОШИБКИ NULL MSG APPEARING
- SQL Server Где <>
- Почему SUM (...) на пустом наборе записей возвращает NULL вместо 0?
Я ожидаю, что это вернет 0, но вместо этого вернет 1. Что дает?
- Как я должен индексировать таблицу для оптимизации, чтобы найти нуль?
- Bizarre WHERE col = NULL поведение
- SQL - Замена a - это нулевое целое с varchar
- Изменение значений из сводной таблицы
- Вставьте пустую строку как NULL, а нуль - в столбце с плавающей точкой
- Изменение агрегатных функций для вывода NULL, когда элемент равен NULL
- Почему оператор TSQL + ведет себя иначе, чем функция агрегации sum ()
- SQL Server - Почему это позволяет мне вставлять пробелы в столбцы с непустым значением?
Вообще говоря, NULL – это не то, что вам следует пытаться сравнить для равенства, что и делает оператор case. Вы можете использовать «Is NULL», чтобы проверить его. Нет никакого ожидания, что NULL != NULL
или NULL = NULL
. Это неопределенное неопределенное значение, а не твердая константа.
– Чтобы охватить вопросы в комментариях –
Если вам нужно получить значение, когда вы можете столкнуться с столбцом NULL, попробуйте это вместо этого:
Case When SomeColumn IS NULL Then 0 Else 1 End
Я считаю, что это должно сработать. Что касается вашего исходного сообщения:
Select Case NULL When NULL then 0 // Checks for NULL = NULL else 1 // NULL = NULL is not true (technically, undefined), else happens end
Проблема в том, что ваш случай автоматически выбирает операции равенства. Это просто не работает с NULL.
В дополнение к другим ответам вам нужно немного изменить синтаксис для CASE
:
SELECT CASE WHEN NULL IS NULL THEN 0 ELSE 1 END;
Использование значения в вашем синтаксисе неявно использует сравнительное сравнение. NULL
неизвестно, и поэтому NULL = NULL
, поэтому с вашим текущим кодом вы всегда получите нуль 1 (geez я тоже сделал).
Чтобы получить нужное поведение, вы можете использовать SET ANSI_NULLS ON ; однако обратите внимание, что это может изменить другой код так, как вы не можете предсказать, и этот параметр устарел – поэтому он перестанет работать вообще в будущей версии SQL Server (см. этот документ SQL Server 2008 ).
Я собирался добавить это как комментарий к ответу Аарона, но он слишком длинный, поэтому я добавлю его как еще один (часть) ответа.
Оператор CASE
фактически имеет два разных режима, простой и поиск.
От BOL:
Выражение CASE имеет два формата:
Простое выражение CASE сравнивает выражение с набором простых выражений для определения результата.
Выбранное выражение CASE оценивает набор булевых выражений для определения результата.
Когда простой CASE
(ваш пример) делает то, что он описывает как сравнение, он сравнивает равенство – т.е. =
Это поясняется в более поздней документации:
Простое выражение CASE работает путем сравнения первого выражения с выражением в каждом предложении WHEN для эквивалентности. Если эти выражения эквивалентны, выражение в предложении THEN будет возвращено.
- Разрешает только проверку равенства.
Потому anything = NULL
что- anything = NULL
всегда является ложным в ANSI SQL (и если вы этого не знали, вам нужно больше читать NULL в SQL, в частности также с поведением в другом найденном сравнении – WHERE x IN (a, b, c)
), вы не можете использовать NULL
в простом случае и всегда ли его сравнивать со значением, с NULL
либо в начальном выражении, либо в списке выражений, которые должны быть сопоставлены.
Если вы хотите проверить NULL
, вам нужно будет использовать конструкцию IF/ELSE
или искомый CASE
с полным выражением.
Я согласен с тем, что это печально, нет версии, которая поддерживает сравнение IS, чтобы было проще писать:
select case colname when IS NULL then 0 else 1 end
Что бы облегчить запись некоторых длинных инструкций CASE
:
select case colname when IS NULL then '' when 1 then 'a' when 2 then 'b' when 3 then 'c' when 4 then 'd' else 'z' end
Но это просто принятие желаемого за действительное …
Опция заключается в использовании ISNULL
или COALESCE
:
select case COALESCE(colname, 999999) -- 999999 is some value never used when 999999 then '' when 1 then 'a' when 2 then 'b' when 3 then 'c' when 4 then 'd' else 'z' end
Но это не всегда отличный вариант.
Вам нужно использовать оператор IS NULL. Стандартные операторы сравнения не работают с NULL.
Ознакомьтесь с этими статьями MSDN об Null, которые могут быть полезны:
- IS [NOT] NULL (Transact-SQL)
- Нулевые значения