Сервер Sql: оператор CASE делает неожиданное поведение при сравнении с NULL

Данный:

Следующий оператор Select:

select case NULL when NULL then 0 else 1 end 

Проблема:

Я ожидаю, что это вернет 0, но вместо этого вернет 1. Что дает?

Вообще говоря, 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)
  • Нулевые значения
  • Как передать переменную Null date в базу данных SQL Server
  • SQL Проверить значения в переменных
  • SQL Server - установить поле в одно текстовое значение, если NULL, добавить другое текстовое значение, если нет
  • SQL Server параметризовал запрос с предложением WHERE с помощью Nulls
  • Значение NULL не проверяется в SQL
  • значение null во внешнем ключе
  • Самый эффективный способ возврата Y / N, если один или несколько столбцов содержат не нулевую стоимость?
  • выберите null как testdate в #temp_table
  • Не удалось добавить столбец «NOT NULL» в пустую таблицу в SQL Server
  • SQL Server: как объединить CASE WHEN IS NULL с оператором OR
  • Изменение позиции NULL при сортировке
  • Interesting Posts

    Массив Int и оператор IN

    Присоединение двух таблиц MSSQL (уникальные значения)

    C # сохранение текста в SQL Server для полнотекстового поиска

    Как сделать массивную вставку

    Как выполнить хранимую процедуру SQL Server в SQL Developer?

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

    Динамически обновлять столбец «Состояние» после «Х» времени

    CONCAT (столбец) OVER (PARTITION BY …)? Групповые конкатенации строк без группировки самого результата

    Как моделировать отношение «многие-ко-многим» в SQL Server?

    Таблица PIVOT только в одной строке в SQL Server?

    T-SQL, чтобы получить список всех баз данных с определенными таблицами

    Хранимая процедура SQL Server + установить сообщение об ошибке из записей таблицы

    В операторе UPDATE есть подсказка NOLOCK, отмеченная в предложении FROM?

    Отсутствует текст команды SQL Dependency

    Не удается получить доступ к SQL Azure DB с веб-сайта Azure, хотя эта же строка подключения работает с локального веб-сайта

    Давайте будем гением компьютера.