Предложение T-SQL CASE: как указать WHEN NULL - PullRequest
204 голосов
/ 13 июля 2010

Я написал примерно такой же оператор T-SQL (оригинальный выглядит иначе, но я хочу привести простой пример):

SELECT first_name + 
    CASE last_name WHEN null THEN 'Max' ELSE 'Peter' END AS Name
FROM dbo.person

В этом операторе нет синтаксических ошибок, но предложение case всегда выбирает ELSE-часть - также, если last_name равно null. Но почему?

Что я хочу сделать, это объединить first_name и last_name, но если last_name равно null, все имя становится пустым:

SELECT first_name +
   CASE last_name WHEN null THEN '' ELSE ' ' + last_name END AS Name 
FROM dbo.person

Вы знаете, где проблема?

Ответы [ 14 ]

342 голосов
/ 13 июля 2010
CASE WHEN last_name IS NULL THEN '' ELSE ' '+last_name END
36 голосов
/ 13 июля 2010

Часть WHEN сравнивается с ==, но вы не можете сравнить ее с NULL. Попробуйте

CASE WHEN last_name is NULL  THEN ... ELSE .. END

вместо или COALESCE:

COALESCE(' '+last_name,'')

('' + last_name равно NULL, когда last_name равно NULL, поэтому в этом случае оно должно возвращать '')

11 голосов
/ 13 июля 2010

По вашему запросу вы также можете сделать это:

SELECT first_name + ' ' + ISNULL(last_name, '') AS Name FROM dbo.person
10 голосов
/ 14 июля 2010

Существует множество решений, но ни одно не объясняет, почему оригинальное утверждение не работает.

CASE last_name WHEN null THEN '' ELSE ' '+last_name

После того, как, когда, есть проверка на равенство, которое должно быть истиной или ложью.

Если одна или обе части сравнения равны нулю, результатом сравнения будет НЕИЗВЕСТНО, что рассматривается как ложь в структуре дела. Смотри: https://www.xaprb.com/blog/2006/05/18/why-null-never-compares-false-to-anything-in-sql/

Чтобы избежать этого, Coalesce - лучший способ.

7 голосов
/ 13 июля 2010

Проблема в том, что нуль не считается равным самому себе, поэтому предложение никогда не совпадает.

Вам необходимо явно проверить на нуль:

SELECT CASE WHEN last_name is NULL THEN first_name ELSE first_name + ' ' + last_name
5 голосов
/ 13 июля 2010

try:

SELECT first_name + ISNULL(' '+last_name, '') AS Name FROM dbo.person

Это добавляет пробел к фамилии, если он нулевой, весь пробел + фамилия переходят в NULL, и вы получаете только имя, в противном случае вы получите первые+ пробел + фамилия.

это будет работать до тех пор, пока задано значение по умолчанию для конкатенации с пустыми строками:

SET CONCAT_NULL_YIELDS_NULL ON 

это не должно беспокоить, поскольку OFFрежим уходит в будущих версиях SQl Server

2 голосов
/ 16 апреля 2015

Проблема в том, что NULL не считается равным чему-либо, даже не самому себе, но странная часть в том, что он также не не равен самому себе.

Рассмотрим следующееоператоры (что, кстати, недопустимо в T-SQL для SQL Server, но допустимо в My-SQL, однако это то, что ANSI определяет для нуля, и может быть проверено даже в SQL Server с помощью операторов case и т. д.)

SELECT NULL = NULL -- Results in NULL

SELECT NULL <> NULL -- Results in NULL

Таким образом, нет правильного / ложного ответа на вопрос, вместо этого ответ также нулевой.

Это имеет много последствий, напримерв

  1. операторах CASE, в которых любое нулевое значение всегда будет использовать предложение ELSE, если только вы явно не используете условие WHEN IS NULL ( NOT условие WHEN NULL )
  2. Конкатенация строк, как
    SELECT a + NULL -- Results in NULL
  3. В выражении WHERE IN или WHERE NOT IN, как если вы хотите получить правильные результаты, убедитесь, что в коррелированном подзапросеотфильтровать все нулевые значения.

Oneможно переопределить это поведение в SQL Server, указав SET ANSI_NULLS OFF, однако это НЕ рекомендуется и не должно выполняться, поскольку это может вызвать много проблем, просто из-за отклонения от стандарта.

(Как примечание, в My-SQL есть возможность использовать специальный оператор <=> для нулевого сравнения.)

Для сравнения, в общих языках программирования ноль обрабатывается как обычное значение и равенСамо по себе, однако, это значение NAN, которое также не равно самому себе, но, по крайней мере, возвращает «ложь» при сравнении его с самим собой (и при проверке на «не равно» разные языки программирования имеют разные реализации).

Обратите внимание, однако, что в базовых языках (т.е. VB и т. Д.) Нет ключевого слова «null», и вместо этого используется ключевое слово «Nothing», которое нельзя использовать при прямом сравнении, а вместо этого необходимо использовать «IS», как в SQLоднако он фактически равен самому себе (при использовании косвенных сравнений).

1 голос
/ 19 ноября 2012
CASE  
    WHEN last_name IS null THEN '' 
    ELSE ' ' + last_name 
END
0 голосов
/ 08 марта 2018

NULL ничего не равно.Оператор case в основном говорит, что когда значение = NULL .. оно никогда не попадет.
Есть также несколько системных хранимых процедур, которые написаны неправильно с вашим синтаксисом.См. Sp_addpullsubscription_agent и sp_who2.
Жаль, что я не знаю, как уведомить Microsoft об этих ошибках, поскольку я не могу изменить хранимые в системе процессы

0 голосов
/ 05 декабря 2017

Используйте функцию CONCAT, доступную в SQL Server 2012 и выше.

SELECT CONCAT([FirstName], ' , ' , [LastName]) FROM YOURTABLE
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...