Obtenir null == null dans SQL

Je souhaite rechercher une table de firebase database sur une colonne nullable. Parfois, la valeur que je recherche est elle-même NULL. Puisque Null est égal à rien, même NULL, en disant

where MYCOLUMN=SEARCHVALUE 

va échouer. En ce moment je dois recourir à

 where ((MYCOLUMN=SEARCHVALUE) OR (MYCOLUMN is NULL and SEARCHVALUE is NULL)) 

Y a-t-il une manière plus simple de dire cela?

(J’utilise Oracle si cela compte)

Vous pouvez faire les choses avec IsNull ou NVL, mais cela ne fera que rendre le moteur plus efficace. Vous appelez des fonctions pour effectuer des conversions de colonnes qui doivent ensuite être comparées.

Utilisez ce que vous avez

 where ((MYCOLUMN=SEARCHVALUE) OR (MYCOLUMN is NULL and SEARCHVALUE is NULL)) 

@Andy Lester affirme que la forme originale de la requête est plus efficace que l’utilisation de NVL. J’ai décidé de tester cette assertion:

  SQL> DECLARE 2 CURSOR B IS 3 SELECT batch_id, equipment_id 4 FROM batch; 5 v_t1 NUMBER; 6 v_t2 NUMBER; 7 v_c1 NUMBER; 8 v_c2 NUMBER; 9 v_b INTEGER; 10 BEGIN 11 -- Form 1 of the where clause 12 v_t1 := dbms_utility.get_time; 13 v_c1 := dbms_utility.get_cpu_time; 14 FOR R IN B LOOP 15 SELECT COUNT(*) 16 INTO v_b 17 FROM batch 18 WHERE equipment_id = R.equipment_id OR (equipment_id IS NULL AND R.equipment_id IS NULL); 19 END LOOP; 20 v_t2 := dbms_utility.get_time; 21 v_c2 := dbms_utility.get_cpu_time; 22 dbms_output.put_line('For clause: WHERE equipment_id = R.equipment_id OR (equipment_id IS NULL AND R.equipment_id IS NULL)'); 23 dbms_output.put_line('CPU seconds used: '||(v_c2 - v_c1)/100); 24 dbms_output.put_line('Elapsed time: '||(v_t2 - v_t1)/100); 25 26 -- Form 2 of the where clause 27 v_t1 := dbms_utility.get_time; 28 v_c1 := dbms_utility.get_cpu_time; 29 FOR R IN B LOOP 30 SELECT COUNT(*) 31 INTO v_b 32 FROM batch 33 WHERE NVL(equipment_id,'xxxx') = NVL(R.equipment_id,'xxxx'); 34 END LOOP; 35 v_t2 := dbms_utility.get_time; 36 v_c2 := dbms_utility.get_cpu_time; 37 dbms_output.put_line('For clause: WHERE NVL(equipment_id,''xxxx'') = NVL(R.equipment_id,''xxxx'')'); 38 dbms_output.put_line('CPU seconds used: '||(v_c2 - v_c1)/100); 39 dbms_output.put_line('Elapsed time: '||(v_t2 - v_t1)/100); 40 END; 41 / For clause: WHERE equipment_id = R.equipment_id OR (equipment_id IS NULL AND R.equipment_id IS NULL) CPU seconds used: 84.69 Elapsed time: 84.8 For clause: WHERE NVL(equipment_id,'xxxx') = NVL(R.equipment_id,'xxxx') CPU seconds used: 124 Elapsed time: 124.01 PL/SQL procedure successfully completed SQL> select count(*) from batch; COUNT(*) ---------- 20903 SQL> 

J’ai été un peu surpris de découvrir à quel point Andy est correct. Cela coûte près de 50% de plus pour faire la solution NVL. Ainsi, même si un morceau de code peut ne pas être aussi soigné ou élégant, il peut être beaucoup plus efficace. J’ai effectué cette procédure plusieurs fois et les résultats étaient presque les mêmes à chaque fois. Bravo à Andy …

Dans Oracle Oracle Database Architecture j’ai vu:

 WHERE DECODE(MYCOLUMN, SEARCHVALUE, 1) = 1 

Je ne sais pas si c’est plus simple, mais j’ai parfois utilisé

 WHERE ISNULL(MyColumn, -1) = ISNULL(SearchValue, -1) 

Remplacer “-1” par une valeur valide pour le type de colonne mais qui ne sera probablement pas trouvée dans les données.

NOTE: J’utilise MS SQL, pas Oracle, donc je ne sais pas si “ISNULL” est valide.

Utilisez NVL pour remplacer null par une valeur factice des deux côtés, comme dans:

 WHERE NVL(MYCOLUMN,0) = NVL(SEARCHVALUE,0) 

Une autre alternative, probablement optimale du sharepoint vue de la requête exécutée, et qui ne sera utile que si vous effectuez une sorte de génération de requête consiste à générer la requête exacte dont vous avez besoin en fonction de la valeur de recherche.

Le pseudocode suit.

 if (SEARCHVALUE IS NULL) { condition = 'MYCOLUMN IS NULL' } else { condition = 'MYCOLUMN=SEARCHVALUE' } runQuery(query,condition) 

Si une valeur hors bande est possible:

 where coalesce(mycolumn, 'out-of-band') = coalesce(searchvalue, 'out-of-band') 

Cela peut également faire le travail dans Oracle.

 WHERE MYCOLUMN || 'X' = SEARCHVALUE || 'X' 

Il y a certaines situations où il bat le test IS NULL avec le OU.

J’ai également été surpris que DECODE vous permette de vérifier NULL contre NULL.

 WITH TEST AS ( SELECT NULL A FROM DUAL ) SELECT DECODE (A, NULL, 'NULL IS EQUAL', 'NULL IS NOT EQUAL') FROM TEST 

Essayer

 WHERE NVL(mycolumn,'NULL') = NVL(searchvalue,'NULL') 

Je pense que ce que vous avez est OK. Vous pourriez peut-être utiliser:

 where NVL(MYCOLUMN, '') = NVL(SEARCHVALUE, '') 

C’est une situation dans laquelle nous nous trouvons beaucoup avec nos fonctions Oracle qui génèrent des rapports. Nous voulons autoriser les utilisateurs à entrer une valeur pour limiter les résultats ou la laisser vide pour renvoyer tous les enregistrements. C’est ce que j’ai utilisé et cela a bien fonctionné pour nous.

 WHERE rte_pending.ltr_rte_id = prte_id OR ((rte_pending.ltr_rte_id IS NULL OR rte_pending.ltr_rte_id IS NOT NULL) AND prte_id IS NULL)