Vous devez distinguer deux situations: vous comparez une COLONNE à NULL, ou vous comparez la RANG (ENREGISTREMENT) entière à NULL.
Considérez la requête suivante:
SELECT
id,
txt,
txt IS NULL AS txt_is_null,
NOT txt IS NULL AS not_txt_is_null,
txt IS NOT NULL AS txt_is_not_null
FROM
(VALUES
(1::integer, NULL::text)
)
AS x(id, txt) ;
Vous obtenez ceci:
+----+-----+-------------+-----------------+-----------------+
| id | txt | txt_is_null | not_txt_is_null | txt_is_not_null |
+----+-----+-------------+-----------------+-----------------+
| 1 | | t | f | f |
+----+-----+-------------+-----------------+-----------------+
C'est, je suppose, ce à quoi vous et moi nous attendrions. Vous vérifiez une COLONNE par rapport à NULL et vous obtenez "txt IS NOT NULL" et "NOT txt IS NULL" sont équivalents.
Cependant, si vous effectuez une vérification différente:
SELECT
id,
txt,
x IS NULL AS x_is_null,
NOT x IS NULL AS not_x_is_null,
x IS NOT NULL AS x_is_not_null
FROM
(VALUES
(1, NULL)
)
AS x(id, txt) ;
Ensuite, vous obtenez
+----+-----+-----------+---------------+---------------+
| id | txt | x_is_null | not_x_is_null | x_is_not_null |
+----+-----+-----------+---------------+---------------+
| 1 | | f | t | f |
+----+-----+-----------+---------------+---------------+
Cela peut surprendre. Une chose semble raisonnable (x EST NUL) et (PAS x EST NUL) sont l'opposé l'une de l'autre. L'autre chose (le fait que ni "x IS NULL" ni "x IS NOT NULL" ne soient vrais), semble bizarre.
Cependant, c'est ce que la documentation PostgreSQL indique qui devrait se produire:
Si l'expression a une valeur de ligne, IS NULL est vrai lorsque l'expression de ligne elle-même est nulle ou lorsque tous les champs de la ligne sont nuls, tandis que IS NOT NULL est vrai lorsque l'expression de ligne elle-même est non nulle et que tous les champs de la ligne sont non nul. En raison de ce comportement, IS NULL et IS NOT NULL ne renvoient pas toujours des résultats inverses pour les expressions à valeur de ligne; en particulier, une expression de valeur de ligne qui contient à la fois des champs null et non null renverra false pour les deux tests. Dans certains cas, il peut être préférable d'écrire la ligne IS DISTINCT FROM NULL ou la ligne IS NOT DISTINCT FROM NULL, qui vérifiera simplement si la valeur globale de la ligne est nulle sans aucun test supplémentaire sur les champs de ligne.
Je dois avouer que je ne pense pas avoir jamais utilisé de comparaison de valeur par ligne contre null, mais je suppose que si la possibilité est là, il pourrait y avoir un cas d'utilisation. Je ne pense pas que ce soit courant de toute façon.