web-dev-qa-db-fra.com

IN Clause avec NULL ou IS NUL

Postgres est la base de données

Puis-je utiliser une valeur NULL pour une clause IN? Exemple:

SELECT *
FROM tbl_name
WHERE id_field IN ('value1', 'value2', 'value3', NULL)

Je veux limiter à ces quatre valeurs.

J'ai essayé la déclaration ci-dessus et cela ne fonctionne pas, il s'exécute mais n'ajoute pas les enregistrements avec NULL id_fields.

J'ai également essayé d'ajouter une condition OR mais cela ne faisait que lancer la requête et la lancer sans fin visible.

SELECT *
FROM tbl_name
WHERE other_condition = bar
AND another_condition = foo
AND id_field IN ('value1', 'value2', 'value3')
OR id_field IS NULL

Aucune suggestion? 

56
Phill Pafford

Une instruction in sera analysée de manière identique à field=val1 or field=val2 or field=val3. Mettre une valeur nulle à l'intérieur se résumera à field=null, ce qui ne fonctionnera pas.

( Commentaire par Marc B )

Je le ferais pour la clarté

SELECT *
FROM tbl_name
WHERE 
(id_field IN ('value1', 'value2', 'value3') OR id_field IS NULL)
80
Daniel A. White

Votre requête échoue à cause de priorité de l'opérateur . AND lie avant OR!
Vous avez besoin d’une paire de parenthèses, ce qui n’est pas une question de "clarté", mais de pure nécessité logique.

SELECT *
FROM   tbl_name
WHERE  other_condition = bar
AND    another_condition = foo
AND   (id_field IN ('value1', 'value2', 'value3') OR id_field IS NULL)

Les parenthèses ajoutées empêchent la liaison AND avant OR. S'il n'y avait pas d'autres conditions WHERE (pas AND), vous ne seriez pas nécessaire parenthèses. La réponse acceptée est un peu trompeuse à cet égard.

16
Erwin Brandstetter
SELECT *
FROM tbl_name
WHERE coalesce(id_field,'unik_null_value') 
IN ('value1', 'value2', 'value3', 'unik_null_value')

Alors que vous éliminez le nul du chèque. Avec une valeur null dans id_field, la fonction coalesce renverrait «unik_null_value» à la place de null et, en ajoutant «unik_null_value» à la liste IN, la requête renverrait des publications où id_field est value1-3 ou null.

7
Ove Halseth

La question à laquelle Daniel a répondu est parfaitement correcte. Je voulais laisser une note concernant NULLS. Nous devons être prudents lors de l'utilisation de l'opérateur NOT IN lorsqu'une colonne contient des valeurs NULL. Vous n'obtiendrez aucune sortie si votre colonne contient des valeurs NULL et que vous utilisez l'opérateur NOT IN. Voici comment cela est expliqué ici http://www.oraclebin.com/2013/01/beware-of-nulls.html , un très bon article que je suis tombé sur et que j'ai pensé partager.

6
Sushant Butta

Remarque: Depuis que quelqu'un a prétendu que le lien externe est mort dans Sushant Butta answer, j'ai posté le contenu ici en tant que réponse séparée.

Méfiez-vous desNULLS.

Aujourd'hui, je suis tombé sur un comportement très étrange de requête en utilisant les opérateurs IN et NOT IN. En fait, je voulais comparer deux tables et déterminer si une valeur de table b existait dans table a ou non et connaître son comportement si la colonne contenait des valeurs null. Je viens donc de créer un environnement pour tester ce comportement.

Nous allons créer la table table_a.

SQL> create table table_a ( a number);
Table created.

Nous allons créer la table table_b.

SQL> create table table_b ( b number);
Table created.

Insérer des valeurs dans table_a.

SQL> insert into table_a values (1);
1 row created.

SQL> insert into table_a values (2);
1 row created.

SQL> insert into table_a values (3);
1 row created.

Insérer des valeurs dans table_b.

SQL> insert into table_b values(4);
1 row created.

SQL> insert into table_b values(3);
1 row created.

Nous allons maintenant exécuter une requête pour vérifier l'existence d'une valeur dans table_a en vérifiant sa valeur à partir de table_b à l'aide de l'opérateur IN.

SQL> select * from table_a where a in (select * from table_b);
         A
----------
         3

Exécutez la requête ci-dessous pour vérifier la non-existence.

SQL> select * from table_a where a not in (select * from table_b);
         A
----------
         1
         2

La sortie est venue comme prévu. Nous allons maintenant insérer une valeur null dans la table table_b et voir comment se comportent les deux requêtes ci-dessus.

SQL> insert into table_b values(null);
1 row created.

SQL> select * from table_a where a in (select * from table_b);
         A
----------
         3

SQL> select * from table_a where a not in (select * from table_b);

no rows selected

La première requête s'est comportée comme prévu, mais que s'est-il passé avec la seconde requête? Pourquoi n'avons-nous pas eu de sortie, qu'est-ce qui aurait dû se passer? Y a-t-il une différence dans la requête? Non .

La modification est dans les données de la table table_b. Nous avons introduit une valeur null dans la table. Mais comment cela se fait-il? Divisons les deux requêtes en opérateurs "AND" et "OR".

Première requête:

La première requête sera traitée en interne à peu près comme ceci. Donc, un null ne créera pas de problème ici car mes deux premiers opérandes seront évalués à true ou false. Mais mon troisième opérande a = null n'évaluera ni true ni false. Il sera évalué à null uniquement.

select * from table_a whara a = 3 or a = 4 or a = null;

a = 3  is either true or false
a = 4  is either true or false
a = null is null

Deuxième requête:

La deuxième requête sera traitée comme ci-dessous. Puisque nous utilisons un opérateur "AND" et que tout autre chose que true dans aucun des opérandes ne me donnera aucune sortie.

select * from table_a whara a <> 3 and a <> 4 and a <> null;

a <> 3 is either true or false
a <> 4 is either true or false
a <> null is null

Alors, comment traitons-nous cela? Nous choisirons toutes les valeurs not null de la table table_b en utilisant l'opérateur NOT IN.

SQL> select * from table_a where a not in (select * from table_b where b is not null);

         A
----------
         1
         2

Soyez donc toujours prudent avec les valeurs NULL dans la colonne lorsque vous utilisez l'opérateur NOT IN.

Attention à NULL !!

2
1000111

Je sais qu'il est tard pour répondre mais que cela pourrait être utile pour quelqu'un d'autre.

SELECT *
FROM (SELECT CASE WHEN id_field IS NULL 
                THEN 0 
                ELSE id_field 
            END AS id_field
      FROM tbl_name) AS tbl
WHERE tbl.id_field IN ('value1', 'value2', 'value3', 0)
0
ch2o