Meilleur moyen de rechercher une "valeur vide ou nulle"


176

Quelle est la meilleure façon de vérifier si la valeur est une chaîne nulle ou vide dans les instructions SQL Postgres?

La valeur peut être une expression longue, il est donc préférable qu'elle ne soit écrite qu'une seule fois.

J'utilise actuellement:

coalesce( trim(stringexpression),'')=''

Mais ça a l'air un peu moche.

stringexpressionpeut être une char(n)colonne ou une expression contenant des char(n)colonnes avec des espaces de fin.

Quelle est la meilleure façon?


3
L'utilisation charest presque toujours le mauvais choix en raison du rembourrage (et du gaspillage d'espace qui en résulte). Mais à part ça: je ne pense pas qu'il y ait de meilleure solution.
a_horse_with_no_name

Pourquoi moche? Logique et lisible.
klin

1
@a_horse_with_no_name: Je pense que oui.
Erwin Brandstetter

Réponses:


285

L'expression stringexpression = ''donne:

TRUE   .. pour ''(ou pour toute chaîne composée uniquement d'espaces avec le type de données char(n))
NULL   .. pour NULL
FALSE .. pour tout le reste

Donc, pour vérifier: " stringexpressionest NULL ou vide" :

(stringexpression = '') IS NOT FALSE

Ou l'approche inverse (peut être plus facile à lire):

(stringexpression <> '') IS NOT TRUE

Fonctionne pour tout type de caractère, y compris char(n). Le manuel sur les opérateurs de comparaison.

Ou utilisez votre expression d'origine sans trim(), ce qui est un bruit coûteux pour char(n)(voir ci-dessous), ou incorrecte pour d'autres types de caractères: les chaînes constituées uniquement d'espaces passeraient comme une chaîne vide.

coalesce(stringexpression, '') = ''

Mais les expressions au sommet sont plus rapides.

Affirmer le contraire est encore plus simple: " stringexpressionn'est ni NULL ni vide" :

stringexpression <> ''

À propos char(n)

Ceci est sur le type de données char(n), abréviation de: character(n). ( char/ charactersont des abréviations de char(1)/ character(1).) Son utilisation est déconseillée dans Postgres :

Dans la plupart des situations text ou character varyingdevrait être utilisé à la place.

Ne pas confondre char(n)avec d' autres, les types de caractères utiles varchar(n), varchar,text ou"char" (avec guillemets).

Dans char(n)une chaîne vide n'est pas différente de toute autre chaîne composée uniquement d'espaces. Tous ces éléments sont pliés en n espaces char(n)par définition du type. Il s'ensuit logiquement que les expressions ci-dessus fonctionnent pourchar(n) aussi bien - tout autant que celles-ci (qui ne fonctionneraient pas pour d'autres types de caractères):

coalesce(stringexpression, '  ') = '  '
coalesce(stringexpression, '') = '       '

Démo

Une chaîne vide équivaut à toute chaîne d'espaces lorsqu'elle est convertie en char(n):

SELECT ''::char(5) = ''::char(5)     AS eq1
     , ''::char(5) = '  '::char(5)   AS eq2
     , ''::char(5) = '    '::char(5) AS eq3;

Résultat:

 eq1 | eq2 | eq3
 ----+-----+----
 t   | t   | t

Teste la "chaîne nulle ou vide" avec char(n):

SELECT stringexpression 
     , stringexpression = ''                   AS base_test
     , (stringexpression = '')  IS NOT FALSE   AS test1
     , (stringexpression <> '') IS NOT TRUE    AS test2
     , coalesce(stringexpression, '') = ''     AS coalesce1
     , coalesce(stringexpression, '  ') = '  ' AS coalesce2
     , coalesce(stringexpression, '') = '  '   AS coalesce3
FROM  (
   VALUES
     ('foo'::char(5))
   , ('')
   , ('   ')                -- not different from '' in char(n)
   , (NULL)
   ) sub(stringexpression);

Résultat:

stringexpression | base_test | test1 | test2 | coalesce1 | coalesce2 | coalesce3
------------------ + ----------- + ------- + ------- + --- -------- + ----------- + -----------
 foo | f | f | f | f | f | F
                  | t | t | t | t | t | t
                  | t | t | t | t | t | t
 null              | null       | t | t | t | t | t

Teste la "chaîne nulle ou vide" avec text:

SELECT stringexpression 
     , stringexpression = ''                   AS base_test
     , (stringexpression = '')  IS NOT FALSE   AS test1
     , (stringexpression <> '') IS NOT TRUE    AS test2
     , coalesce(stringexpression, '') = ''     AS coalesce1
     , coalesce(stringexpression, '  ') = '  ' AS coalesce2
     , coalesce(stringexpression, '') = '  '   AS coalesce3
FROM  (
   VALUES
     ('foo'::text)
   , ('')
   , ('   ')                -- different from '' in a sane character types
   , (NULL)
   ) sub(stringexpression);

Résultat:

stringexpression | base_test | test1 | test2 | coalesce1 | coalesce2 | coalesce3
------------------ + ----------- + ------- + ------- + --- -------- + ----------- + -----------
 foo | f | f | f | f | f | F
                  | t | t | t | t | f | F
                  | f | f | f | f | f | F
 null              | null       | t | t | t | t | F

db <> violon ici
Ancien sqlfiddle

En relation:


2
@a_horse_with_no_name: OP demande le fichier best way to check if value is null or empty string. L' trim()appel est (comparativement) cher - et tout simplement pas nécessaire. J'ai ajouté plus sur char(n)et "chaîne vide".
Erwin Brandstetter

1
Vous avez écrit que toute expression de chaîne contenant uniquement des espaces est égale à ''. Puis-je retirer la garniture et l'utiliser coalesce(stringexpression,'')=''pour vérifier. Cela me semble plus lisible que votre réponse.
Andrus

1
@Andrus: Oui, vous pouvez. J'ai ajouté cela et quelques autres à la réponse.
Erwin Brandstetter

3
select coalesce(' ', '') = '' renvoie false. Donc TRIM () est requis
Andrus

1
Mais coalesce(' '::char(5), '') = ''non. J'utiliserais dans tous les cas l'une des deux principales expressions, qui fonctionnent pour n'importe quel type de caractère et sont les plus rapides et les plus propres.
Erwin Brandstetter

46

Pour vérifier les valeurs nulles et vides:

coalesce(string, '') = ''

Pour vérifier les valeurs nulles, vides et espaces (coupez la chaîne)

coalesce(TRIM(string), '') = ''

3
J'aime cette simplicité / clarté de cette réponse.
stwr667

12

La vérification de la longueur de la chaîne fonctionne également et est compacte:

where length(stringexpression) > 0;

Avez-vous vérifié cela pour le cas NULL?
Flinsch le

1
Oui je l'ai fait. Il ne renvoie pas de champs de chaîne vides ou nuls.
yglodt le

Si vous avez juste besoin de vérifier uniquement les valeurs vides, essayez ceci -> where length(stringexpression) = 0;. Cela fonctionne pour moi.
Kushan Gunasekera

2

S'il peut y avoir des espaces de fin vides, il n'y a probablement pas de meilleure solution. COALESCEest juste pour des problèmes comme le vôtre.


1

Quelque chose que j'ai vu des gens utiliser est stringexpression > ''. Ce n'est peut-être pas le plus rapide, mais il se trouve être l'un des plus courts.

Je l'ai essayé sur MS SQL ainsi que sur PostgreSQL.



0

Ma façon préférée de comparer les champs nullables est: NULLIF (nullablefield,: ParameterValue) IS NULL AND NULLIF (: ParameterValue, nullablefield) IS NULL. Ceci est encombrant mais est d'une utilisation universelle alors que Coalesce est impossible dans certains cas.

La seconde utilisation inverse de NULLIF est due au fait que "NULLIF (nullablefield,: ParameterValue) IS NULL" retournera toujours "true" si le premier paramètre est nul.


0

Si la base de données ayant un grand nombre d'enregistrements null checkpeut prendre plus de temps, vous pouvez utiliser la vérification nulle de différentes manières, comme: 1) where columnname is null 2) where not exists() 3)WHERE (case when columnname is null then true end)


0

Beaucoup de réponses sont le moyen le plus court, pas nécessairement le meilleur si la colonne contient beaucoup de valeurs nulles. L'interruption des vérifications permet à l'optimiseur d'évaluer la vérification plus rapidement car il n'a pas à travailler sur l'autre condition.

(stringexpression IS NOT NULL AND trim(stringexpression) != '')

La comparaison de chaînes n'a pas besoin d'être évaluée car la première condition est fausse.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.