Note: Étant donné que quelqu'un prétend que le lien externe est mort dans la réponse de Sushant Butta, j'ai posté le contenu ici comme une réponse séparée.
Méfiez-vous des NULLS.
Aujourd'hui, j'ai rencontré un comportement très étrange de la requête lors de l'utilisation des opérateurs IN et NOT IN
. En fait, je voulais comparer deux tables et savoir si une valeur de table b
existait dans table a
ou non, et connaître son comportement si la colonne contient des valeurs null
. J'ai donc créé un environnement pour tester ce comportement.
Nous allons créer la table table_a
.
SQL> create table table_a ( a number);
Table créée.
Nous allons créer la table table_b
.
SQL> create table table_b ( b number);
Table créée.
Insérez des valeurs dans table_a
.
SQL> insert into table_a values (1);
1 ligne créée.
SQL> insert into table_a values (2);
1 ligne créée.
SQL> insert into table_a values (3);
1 ligne créée.
Insérez des valeurs dans table_b
.
SQL> insert into table_b values(4);
1 ligne créée.
SQL> insert into table_b values(3);
1 ligne créée.
Nous allons maintenant exécuter une requête pour vérifier l'existence d'une valeur dans table_a
en vérifiant sa valeur de table_b
en utilisant 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 arrivée comme prévu. Maintenant, nous allons insérer une valeur null
dans la table table_b
et voir comment les deux requêtes ci-dessus se comportent.
SQL> insert into table_b values(null);
1 ligne créée.
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);
aucune ligne sélectionnée
La première requête s'est comportée comme prévu mais qu'est-il arrivé à la deuxième requête? Pourquoi n'avons-nous obtenu aucune sortie, que se serait-il passé ? Y a-t-il une différence dans la requête? Non.
Le changement concerne les données de la table table_b
. Nous avons introduit une valeur null
dans la table. Mais comment se fait-il qu'il se comporte ainsi ? Séparons les deux requêtes en utilisant les opérateurs "AND"
et "OR"
.
Première Requête:
La première requête sera traitée en interne quelque chose comme cela. Ainsi, un null
ne posera pas de problème ici car mes deux premiers opérandes évalueront soit à true
soit à false
. Mais mon troisième opérande a = null
ne s'évaluera ni à true
ni à false
. Il s'évaluera seulement à null
.
select * from table_a whara a = 3 or a = 4 or a = null;
a = 3 est soit vrai soit faux
a = 4 est soit vrai soit faux
a = null est null
Deuxième Requête:
La deuxième requête sera traitée comme suit. Puisque nous utilisons un opérateur "AND"
et que toute valeur autre que true
dans l'un des opérandes ne me donnera aucune sortie.
select * from table_a whara a <> 3 and a <> 4 and a <> null;
a <> 3 est soit vrai soit faux
a <> 4 est soit vrai soit faux
a <> null est null
Comment gérons-nous cela ? Nous allons prendre toutes les valeurs not null
de la table table_b
tout 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
Alors soyez toujours attentif aux valeurs NULL
dans la colonne lors de l'utilisation de l'opérateur NOT IN
.
Méfiez-vous des NULL!!
17 votes
Une instruction
dans
sera analysée de la même manière quechamp=val1 ou champ=val2 ou champ=val3
. Mettre un nul là-dedans se résumera àchamp=null
ce qui ne fonctionnera pas.1 votes
La deuxième requête devrait être correcte. Quelles autres choses sont dans votre clause
where
?0 votes
@Daniel A. White, mis à jour pour refléter la requête avec plus de conditions