web-dev-qa-db-fra.com

Comparaison null entre Oracle/PL SQL/SQL dans la clause where

Juste une question sur le traitement des valeurs nulles dans une requête.

Par exemple, j'ai le tableau suivant avec les champs et les valeurs suivants

TABLEX
Column1
1        
2        
3      
4        
5      
---------
Column2
null
A
B
C
null

Je passe une variableY sur une procédure spécifique. Dans la procédure se trouve un curseur comme celui-ci

CURSOR c_results IS
SELECT * FROM TABLEX where column2 = variableY

maintenant le problème est variableY peut être null, A, B ou C si la variableY est null, je veux sélectionner tous les enregistrements où column2 est null, sinon où column2 est A, B ou C.

Je ne peux pas faire le curseur/requête ci-dessus parce que si variableY est nul, cela ne fonctionnera pas car la comparaison devrait être

CURSOR c_results IS
SELECT * FROM TABLEX where column2 IS NULL

Quel curseur/requête devrais-je utiliser pour accueillir la variable null ou string?.

Désolé si ma question est un peu déroutante. Je ne suis pas très doué pour expliquer les choses. Merci d'avance.

18
user2447740

Soit produire un code SQL différent en fonction du contenu de ce paramètre, soit modifier votre code SQL de la manière suivante:

WHERE (column2 = variableY) OR (variableY IS NULL AND column2 IS NULL)

Ask Tom d'Oracle dit:

where decode( col1, col2, 1, 0 ) = 0  -- finds differences

ou

where decode( col1, col2, 1, 0 ) = 1  -- finds sameness - even if both NULL

Comparaison en toute sécurité des colonnes NULL en tant qu'égales

6
rghome

Vous pourriez utiliser quelque chose comme:

SELECT * FROM TABLEX WHERE COALESCE(column2, '') = COALESCE(variableY, '')

(COALESCE prend la première valeur non NULL)

Notez que cela ne fonctionnera que si le contenu de la colonne ne peut pas être '' (chaîne vide). Sinon, cette instruction échouera car NULL correspondra '' (chaîne vide).

(edit) Vous pourriez également considérer:

SELECT * FROM TABLEX WHERE COALESCE(column2, 'a string that never occurs') = COALESCE(variableY, 'a string that never occurs')

Cela corrigera l'hypothèse "échec".

2
Stef Heyenrath

Cela peut ne pas être approprié en fonction des données que vous consultez, mais une astuce que j'ai vue (et utilisée) consiste à comparer NVL (nom du champ, somenonexistentvalue). 

Par exemple, si AGE est une colonne facultative, vous pouvez utiliser:

if nvl(table1.AGE,-1) = nvl(table2.AGE,-1)

Cela repose sur l'existence d'une valeur que vous savez ne serez jamais autorisée. L'âge est un bon exemple: salaire, numéros de séquence et autres données numériques qui ne peuvent être négatives. Les cordes peuvent être plus compliquées bien sûr - vous pouvez dire que personne ne s'appellera 'xyzzymaryhadalittlelamb "ou quelque chose du genre, mais le jour où vous courez avec cette hypothèse, vous SAVEZ qu'ils vont embaucher quelqu'un avec ce nom !!

Tout ce qui a été dit: "où a = b ou (a est nul et b est nul)" est la méthode traditionnelle pour le résoudre. Ce qui est regrettable, car même les programmeurs expérimentés oublient parfois cette partie de la chose. 

1
JOATMON

Vous pouvez utiliser DUMP:

SELECT * 
FROM TABLEX 
WHERE DUMP(column2) = DUMP(variableY);

DBFiddle Demo

Avertissement: Ceci n'est pas une expression compatible avec SARG, il n'y aura donc pas d'utilisation d'index.

Avec cette approche, vous n'avez pas besoin de rechercher une valeur qui n'existera pas dans vos données (telle que NVL/COALESCE).

0
Lukasz Szozda

Essayez d’utiliser la fonction ISNULL(). vous pouvez vérifier si la variable est null et, le cas échéant, définir une valeur de retour par défaut. Camparing null to null n'est pas vraiment possible. rappelez-vous: null <> null

0
karel
WHERE variableY is null or column2 = variableY 

for example:
create table t_abc (
id number(19) not null,
name varchar(20)
);

insert into t_abc(id, name) values (1, 'name');
insert into t_abc(id, name) values (2, null);
commit;

select * from t_abc where null is null or name = null;
--get all records

select * from t_abc where 'name' is null or name = 'name';
--get one record with name = 'name'
0
Kevin