T-SQL CASE: как указать WHEN NULL

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

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

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

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

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

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

Ответ 1

CASE WHEN last_name IS NULL THEN '' ELSE ' '+last_name END

Ответ 2

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

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

или COALESCE:

COALESCE(' '+last_name,'')

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

Ответ 3

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

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

Ответ 4

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

Вам нужно явно указать значение null:

SELECT CASE WHEN last_name is NULL THEN first_name ELSE first_name + ' ' + last_name

Ответ 5

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

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

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

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

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

Ответ 6

попробовать:

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

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

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

SET CONCAT_NULL_YIELDS_NULL ON 

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

Ответ 7

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

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

SELECT NULL = NULL -- Results in NULL

SELECT NULL <> NULL -- Results in NULL

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

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

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

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

(В качестве побочного примечания в My-SQL существует опция использования специального оператора <=> для нулевого сравнения.)

Для сравнения, в общем случае языки программирования null обрабатываются как регулярное значение и равно самому себе, однако значение NAN также не равно самому себе, но по крайней мере оно возвращает "false" при сравнении его с самим собой, (и при проверке не равны разные языки программирования имеют разные реализации).

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

Ответ 8

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

Ответ 9

Когда вы расстраиваетесь, попробуйте это:

CASE WHEN last_name IS NULL THEN '' ELSE ' '+last_name END

Попробуйте вместо этого:

CASE LEN(ISNULL(last_Name,''))
WHEN 0 THEN '' 
ELSE ' ' + last_name
END AS newlastName

LEN(ISNULL(last_Name,'')) измеряет количество символов в этом столбце, которое будет равно нулю, пустое или NULL, поэтому WHEN 0 THEN будет оценивать значение true и возвращать '' как ожидалось.

Надеюсь, это полезная альтернатива.

Я включил этот тестовый пример для SQL Server 2008 и выше:

DECLARE @last_Name varchar(50) = NULL

SELECT 
CASE LEN(ISNULL(@last_Name,''))
WHEN 0 THEN '' 
ELSE 'A ' + @last_name
END AS newlastName

SET @last_Name = 'LastName'

SELECT 
CASE LEN(ISNULL(@last_Name,''))
WHEN 0 THEN '' 
ELSE 'A ' + @last_name
END AS newlastName

Ответ 10

Джейсон ошибся, поэтому это работает...

Кто-нибудь может подтвердить другие версии платформы? SQL Server:

SELECT
CASE LEN(ISNULL(last_name,'')) 
WHEN 0 THEN '' 
ELSE ' ' + last_name
END AS newlastName

MySQL:

SELECT
CASE LENGTH(IFNULL(last_name,'')) 
WHEN 0 THEN '' 
ELSE ' ' + last_name
END AS newlastName

Oracle:

SELECT
CASE LENGTH(NVL(last_name,'')) 
WHEN 0 THEN '' 
ELSE ' ' + last_name
END AS newlastName

Ответ 11

Вы можете использовать функцию IsNull

select 
    isnull(rtrim(ltrim([FirstName]))+' ','') +
    isnull(rtrim(ltrim([SecondName]))+' ','') +
    isnull(rtrim(ltrim([Surname]))+' ','') +
    isnull(rtrim(ltrim([SecondSurname])),'')
from TableDat

если один столбец равен null, вы получите пустой char

Совместимость с Microsoft SQL Server 2008 +

Ответ 12

Я попробовал кастинг на строку и тестирование строки нулевой длины, и она сработала.

CASE 
   WHEN LEN(CAST(field_value AS VARCHAR(MAX))) = 0 THEN 
       DO THIS
END AS field 

Ответ 13

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

SELECT CONCAT([FirstName], ' , ' , [LastName]) FROM YOURTABLE