242 votes

Clause CASE en T-SQL : Comment spécifier WHEN NULL

J'ai écrit une déclaration T-SQL similaire à celle-ci (l'original est différent mais je veux donner un exemple simple ici) :

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

Cette déclaration ne comporte aucune erreur de syntaxe, mais la clause de cas choisit toujours la partie ELSE, même si le nom de famille est nul. Mais pourquoi ?

Ce que je veux faire, c'est réunir le prénom et le nom, mais si le nom est nul, le nom entier devient nul :

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

Savez-vous où est le problème ?

393voto

Marcelo Cantos Points 91211
CASE WHEN last_name IS NULL THEN '' ELSE ' '+last_name END

5 votes

La suggestion de COALESCE de @Luther est meilleure que ma réponse. Elle est légèrement moins efficace, mais beaucoup plus élégante.

0 votes

Il peut être utile de le manipuler avec quelque chose comme ceci, ou quelque chose de ce genre : COALESCE(nom_famille, '') L'instruction case, bien que concise, est à mon avis moins facile à maintenir que COALESCE dans les grandes requêtes. Au final, vous obtenez le même résultat. Si vous avez besoin d'optimiser, vérifiez les plans d'exécution, mais je n'ai pas remarqué une grande différence.

1 votes

COALESCE se traduit essentiellement, en interne, par CASE . Le problème avec le CASE est que last_name est évaluée deux fois et elle peut entraîner d'autres effets secondaires - voir cette excellente article . Pour résoudre ce qui a été demandé, je préférerais aller avec ISNULL(' '+ last_name, '') mentionné dans commentaire ci-dessous.

46voto

Nordic Mainframe Points 13717

La partie WHEN est comparée avec ==, mais vous ne pouvez pas vraiment comparer avec NULL. Essayez

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

à la place ou COALESCE :

COALESCE(' '+last_name,'')

(''+nom_famille est NULL lorsque nom_famille est NULL, donc il devrait retourner '' dans ce cas)

0 votes

Ok, merci pour l'information avec le == dans la partie WHEN. Je ne le savais pas. Avec COALESCE, cela fonctionne bien aussi. Je n'avais pas pensé qu'il y avait autant de possibilités de faire cela.

1 votes

Je sens que ' ' + est superflue (et peut nuire aux performances car elle entraîne la copie de chaînes).

17voto

kamahl Points 424

Il existe de nombreuses solutions, mais aucune ne permet de comprendre pourquoi la déclaration initiale ne fonctionne pas.

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

Après le "when", il y a une vérification de l'égalité, qui doit être vraie ou fausse.

Si l'une ou les deux parties d'une comparaison sont nulles, le résultat de la comparaison sera UNKNOWN, qui est traité comme false dans une structure de cas. Voir : https://www.xaprb.com/blog/2006/05/18/why-null-never-compares-false-to-anything-in-sql/

Pour éviter cela, Coalesce est le meilleur moyen.

13voto

Ian Jacobs Points 4165

Compte tenu de votre demande, vous pouvez également procéder ainsi :

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

2 votes

Cela ajoute un espace redondant lorsque last_name est nul, ce que le PO cherchait à éviter.

7 votes

Mieux utiliser ISNULL(' '+ last_name, '') pour éviter la redondance de l'espace.

0 votes

Oui, j'ai réalisé ça après avoir posté. J'ai pensé que je devais le laisser puisque ça a résolu la partie qui lui posait problème.

8voto

b0fh Points 637

Le problème est que null n'est pas considéré comme égal à lui-même, ce qui fait que la clause ne correspond jamais.

Vous devez vérifier les nullités de manière explicite :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X