Eu escrevi uma instrução T-SQL semelhante a esta (a original parece diferente, mas 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 instrução não possui nenhum erro de sintaxe, mas a cláusula case escolhe sempre a parte ELSE - também se o last_name for nulo. Mas por que?
O que eu quero fazer é unir first_name e last_name, mas se last_name for nulo, o nome inteiro se tornará nulo:
SELECT first_name +
CASE last_name WHEN null THEN '' ELSE ' ' + last_name END AS Name
FROM dbo.person
Você sabe onde está o problema?
COALESCE
basicamente traduz internamente paraCASE
. O problema com o CASE é quelast_name
é avaliado duas vezes e pode levar a outros efeitos colaterais - consulte este excelente artigo . Para resolver o que foi solicitado, prefiroISNULL(' '+ last_name, '')
mencionar o comentário abaixo.A parte WHEN é comparada com ==, mas você realmente não pode comparar com NULL. Experimentar
em vez disso ou COALESCE:
('' + last_name é NULL quando last_name é NULL, portanto, ele deve retornar '' nesse caso)
fonte
Existem muitas soluções, mas nenhuma cobre por que a declaração original não funciona.
Após o quando, há uma verificação de 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. Veja: https://www.xaprb.com/blog/2006/05/18/why-null-never-compares-false-to-anything-in-sql/
Para evitar isso, Coalesce é o melhor caminho.
fonte
Dada sua consulta, você também pode fazer isso:
fonte
ISNULL(' '+ last_name, '')
para evitar o espaço redundante.O problema é que nulo não é considerado igual a si mesmo, portanto a cláusula nunca corresponde.
Você precisa verificar se há nulo explicitamente:
fonte
experimentar:
Isso adiciona o espaço ao sobrenome, se for nulo, todo o espaço + sobrenome passa a NULL e você obtém apenas um primeiro nome; caso contrário, obtém um primeiro + espaço + sobrenome.
isso funcionará desde que a configuração padrão para concatenação com cadeias nulas seja definida:
isso não deve ser uma preocupação, pois o
OFF
modo está desaparecendo em versões futuras do SQl Serverfonte
A questão é que NULL não é considerado igual a qualquer coisa, mesmo que não seja ela mesma, mas a parte estranha é que também não é igual a ela mesma.
Considere as seguintes instruções (que são ilegais no BT-SQL Server T-SQL, mas são válidas no My-SQL, no entanto, é isso que o ANSI define como nulo e pode ser verificado mesmo no SQL Server usando instruções de caso etc.)
SELECT NULL = NULL -- Results in NULL
SELECT NULL <> NULL -- Results in NULL
Portanto, não há resposta verdadeira / falsa para a pergunta, mas a resposta também é nula.
Isso tem muitas implicações, por exemplo, em
WHEN NULL
condição )SELECT a + NULL -- Results in NULL
Pode-se substituir esse comportamento no SQL Server, especificando
SET ANSI_NULLS OFF
, no entanto, isso NÃO é recomendado e não deve ser feito, pois pode causar muitos problemas, simplesmente devido ao desvio do padrão.(Como uma observação lateral, no My-SQL há uma opção para usar um operador especial
<=>
para comparação nula.)Em comparação, nas linguagens de programação gerais, nulo é tratado é um valor regular e é igual a si mesmo; no entanto, é 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 se não é igual a diferentes linguagens de programação, tem implementações diferentes).
Observe, no entanto, que nas linguagens Básicas (por exemplo, VB etc.) não existe uma palavra-chave 'nula' e, em vez disso, é usada a palavra-chave 'Nada', que não pode ser usada em comparação direta e, em vez disso, é necessário usar 'IS' como no SQL, no entanto, é de fato igual a si mesmo (ao usar comparações indiretas).
fonte
fonte
Quando você fica frustrado tentando isso:
Experimente este:
LEN(ISNULL(last_Name,''))
mede o número de caracteres nessa coluna, que será zero se estiver vazio ou NULL; portanto,WHEN 0 THEN
será avaliado como true e retornará o '' conforme o esperado.Espero que seja uma alternativa útil.
Eu incluí este caso de teste para o sql server 2008 e acima:
fonte
Jason pegou um erro, então isso funciona ...
Alguém pode confirmar as outras versões da plataforma?
Servidor SQL:
MySQL:
Oráculo:
fonte
Você pode usar a função IsNull
se uma coluna for nula, você receberá um caractere vazio
Compatível com Microsoft SQL Server 2008+
fonte
Use a função CONCAT disponível no SQL Server 2012 em diante.
fonte
Tentei converter para uma string e testar uma string de comprimento zero e funcionou.
fonte
NULL não é igual a nada. A declaração de caso está basicamente dizendo quando o valor = NULL .. nunca será atingido.
Existem também vários procedimentos armazenados do sistema que são gravados incorretamente com sua sintaxe. Consulte sp_addpullsubscription_agent e sp_who2.
Gostaria de saber como notificar a Microsoft sobre esses erros, pois não consigo alterar os procs armazenados no sistema.
fonte