web-dev-qa-db-fra.com

Vérifier si un champ composite Postgres est nul / vide

Avec types composites postgres vous pouvez essentiellement construire un champ avec la structure étant définie comme une autre table. J'ai le champ composite appelé "destinataire" de type "personne". Ce champ de destinataire est souvent laissé vide dans mon scénario spécifique. Quelle est la bonne façon de vérifier si un champ composite est vide. J'ai essayé:

select * from bla where recipient is not null
select * from bla where recipient is null
select * from bla where recipient = null
select * from bla where recipient != null

Dans tous ces cas, il ne renvoie rien. Alors, comment vérifiez-vous correctement si une valeur composite est vide ou non?

[~ # ~] mise à jour [~ # ~]

Après un peu plus de lecture, il semble que c'est mon problème:

On peut penser que !(x IS NULL) = x IS NOT NULL est vrai dans tous les cas. Mais il existe une exception - les types composites. Lorsqu'un champ d'une valeur composite est NULL et qu'un autre champ est NOT NULL, Le résultat des deux opérateurs est faux. IS NULL Est vrai, uniquement lorsque tous les champs sont NULL. IS NOT NULL Est vrai, uniquement lorsque tous les champs sont NOT NULL. Dans tous les cas intermédiaires, les deux opérateurs renvoient false.

J'ai certains champs qui sont nuls et d'autres qui ne le sont pas. J'espérais que le champ serait considéré comme NON NUL, si un élément du champ composite n'est pas nul ... pas quand TOUS ne le sont pas. Y a-t-il un moyen de contourner cela autre que de vérifier chaque champ?

22
coderama

IS NULL et IS NOT NULL fonctionne aussi pour les types complexes, donc ces deux devraient être appropriés:

select * from bla where recipient is not null
select * from bla where recipient is null
20
Mureinik

Pour intercepter les cas où pas tous les champs de la valeur composite (ligne/enregistrement) sont NULL:

SELECT *
FROM   bla
WHERE  NOT (recipient IS NULL);

<row-type> is NULL renvoie uniquement TRUE si tous les champs sont NULL.
<row-type> is NOT NULL renvoie uniquement TRUE si tous les champs sont NOT NULL.

Les parenthèses sont facultatives. La priorité des opérateurs fonctionne de toute façon en notre faveur.

Test de ligne/enregistrement pour NULL

Démontrer les différentes options:

CREATE TEMP TABLE recipient (r text, i int);  -- to register the row type

SELECT recipient
     , recipient IS NULL         AS all_null
     , recipient IS NOT NULL     AS all_notnull
     , NOT recipient IS NULL     AS some_notnull
     , NOT recipient IS NOT NULL AS some_null
FROM (
   VALUES
    (('foo', 1   )::recipient)
  , ((NULL , 2   )::recipient)
  , ((NULL , NULL)::recipient)
   ) AS tbl(recipient);

Résultat:

 recipient | all_null | all_notnull | some_notnull | some_null
-----------+----------+-------------+--------------+-----------
 (foo,1)   | f        | t           | t            | f
 (,2)      | f        | f           | t            | t
 (,)       | t        | f           | f            | t

SQL Fiddle.

En relation:

14
Erwin Brandstetter