T-SQL CASE Clause: How to specify WHEN NULL

eu escrevi uma declaração T-SQL semelhante a esta (a original parece diferente, mas eu quero dar um exemplo fácil aqui):

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

esta Declaração não tem quaisquer erros de sintaxe, mas a cláusula case-clause sempre escolhe a outra parte-também se o last_name for nulo. Mas Porquê?

O Que Eu quero fazer é unir o primeiro nome e o último nome, mas se o último nome for nulo o nome inteiro torna-se nulo:

SELECT first_name +
   CASE last_name WHEN null THEN '' ELSE ' ' + last_name END AS Name 
FROM dbo.person
Sabes onde está o problema?

 191
Author: Michał Powaga, 2010-07-13

14 answers

CASE WHEN last_name IS NULL THEN '' ELSE ' '+last_name END
 322
Author: Marcelo Cantos, 2011-10-23 18:55:56

A parte quando é comparada com==, mas você não pode realmente comparar com NULL. Tenta

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

Em vez disso ou carvão:

COALESCE(' '+last_name,'')

(''+last_name is NULL when last_name is NULL, so it should return " in that case)

 34
Author: Nordic Mainframe, 2010-07-13 13:36:57

Dada a sua pergunta, também pode fazer isto:

SELECT first_name + ' ' + ISNULL(last_name, '') AS Name FROM dbo.person
 11
Author: Ian Jacobs, 2010-07-13 13:37:31

O problema é que null não é considerado igual a si mesmo, portanto a cláusula nunca corresponde.

Você precisa verificar se null explicitamente:

SELECT CASE WHEN last_name is NULL THEN first_name ELSE first_name + ' ' + last_name
 7
Author: b0fh, 2010-07-13 13:37:40
Há muitas soluções, mas nenhuma cobre a razão pela qual a declaração original não funciona.
CASE last_name WHEN null THEN '' ELSE ' '+last_name
Depois do "quando", há uma verificação da igualdade, que deve ser verdadeira ou falsa.

Se uma ou ambas as partes de uma comparação for nula, o resultado da comparação será desconhecido, que é tratado como falso em uma estrutura de caso. Ver: https://www.xaprb.com/blog/2006/05/18/why-null-never-compares-false-to-anything-in-sql/

Para evitar isto, o Coalesce é o melhor. forma.
 7
Author: kamahl, 2017-05-23 13:24:48

Tenta:

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

Isto adiciona o espaço ao último nome, se for nulo, o espaço inteiro+último nome vai para NULL e só obtém um primeiro nome, caso contrário obtém um firts+espaço+último nome.

Isto irá funcionar desde que a configuração por omissão para a concatenação com cadeias nulas seja definida:

SET CONCAT_NULL_YIELDS_NULL ON 

Isto não deve ser uma preocupação, uma vez que o modo OFF está a desaparecer nas versões futuras do servidor SQl

 4
Author: KM., 2010-07-13 14:51:54

A questão é que NULL não é considerado igual a nada mesmo não a si mesmo, mas a parte estranha é que também não é igual a si mesmo.

Considere as seguintes declarações (que é BTW ilegal no servidor SQL T-SQL, mas é válido no My-SQL, no entanto isto é o que ANSI define para null, e pode ser verificado mesmo no servidor SQL usando declarações de caso etc.)

SELECT NULL = NULL -- Results in NULL

SELECT NULL <> NULL -- Results in NULL

Então não há resposta verdadeira ou falsa para a pergunta., em vez disso, a resposta também é nula.

Isto tem muitas implicações, por exemplo em

  1. extratos de casos, nos quais qualquer valor nulo irá sempre usar a outra cláusula, a menos que você use explicitamente a condição de quando é nulo (Não a condição de WHEN NULL
  2. concatenação de cordas, como
    SELECT a + NULL -- Results in NULL
  3. em um onde dentro ou onde não em cláusula, como se você quiser resultados corretos certifique-se na sub-consulta correlacionada para filtrar qualquer nulo valores.

Pode-se anular este comportamento no servidor SQL especificando {[[4]}, no entanto este é Não recomendado e não deve ser feito como pode causar muitos problemas, simplesmente porque o desvio do padrão.

(como nota lateral, no My-SQL existe uma opção para usar um operador especial <=> para comparação nula.)

Em comparação, em linguagens de programação gerais null é tratado é um valor regular e é igual a si mesmo, no entanto o é o valor NAN que é também não é igual a si mesmo, mas pelo menos retorna 'false' ao compará-lo a si mesmo, (e ao verificar não é igual a linguagens de programação diferentes têm implementações diferentes).

Note No entanto que nas línguas de base (isto é, VB, etc.) não existe palavra-chave' null 'E em vez disso se usa a palavra-chave 'nada', que não pode ser usada em comparação direta e em vez disso é preciso usar' IS ' como em SQL, no entanto, é de fato igual a si mesmo (ao usar comparações indiretas).

 2
Author: yoel halb, 2015-04-16 01:09:16
CASE  
    WHEN last_name IS null THEN '' 
    ELSE ' ' + last_name 
END
 1
Author: Linda, 2012-11-19 15:54:54
O Jason apanhou um erro, então isto funciona... Alguém pode confirmar as outras versões da plataforma?
Servidor SQL:
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

Oráculo:

SELECT
CASE LENGTH(NVL(last_name,'')) 
WHEN 0 THEN '' 
ELSE ' ' + last_name
END AS newlastName
 0
Author: Chef Slagle, 2015-10-29 15:43:45

Quando ficas frustrado a tentar isto:

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

Tenta este em vez disso.:

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

LEN(ISNULL(last_Name,'')) mede o número de caracteres nessa coluna, que será zero quer esteja vazia, ou nula, portanto WHEN 0 THEN irá avaliar para true e devolver o " como esperado.

Espero que esta seja uma alternativa útil.

Incluí este teste para o servidor sql 2008 e superior:

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
 0
Author: Chef Slagle, 2016-12-08 21:25:55

Pode usar a função IsNull

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

Se uma coluna for nula, obteria um char vazio

Compatível com o Microsoft SQL Server 2008 +

 0
Author: Molem, 2017-05-19 14:25:28

Utilize a função CONCAT disponível no servidor SQL 2012 em diante.

SELECT CONCAT([FirstName], ' , ' , [LastName]) FROM YOURTABLE
 0
Author: TSQL, 2017-12-05 05:03:29
Tentei lançar uma corda e testar uma corda de tamanho zero e funcionou.
CASE 
   WHEN LEN(CAST(field_value AS VARCHAR(MAX))) = 0 THEN 
       DO THIS
END AS field 
 0
Author: user2463829, 2017-12-05 05:03:42

NULL não é igual a nada. A declaração de caso está basicamente dizendo Quando o valor = nulo .. nunca vai bater.
Existem também vários procedimentos armazenados no sistema que são escritos incorretamente com a sua sintaxe. Ver sp_addpullsubscription_agent e sp_who2.
Gostaria de saber como notificar a Microsoft desses erros como eu não sou capaz de mudar o sistema armazenado procs.

 0
Author: Joshua Walker, 2018-03-08 20:29:54