在SQL中获得null == null

我希望在可空列上search数据库表。 有时我正在search的值本身是NULL。 由于空等于无,甚至空,说

where MYCOLUMN=SEARCHVALUE 

将失败。 现在我不得不求助于

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

有一种更简单的方式来说明吗?

(如果有问题,我正在使用Oracle)

你可以做IsNull或NVL的东西,但这只是让引擎做更多的工作。 您将调用函数来进行列转换,然后必须将结果进行比较。

使用你有什么

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

@Andy Lester断言查询的原始forms比使用NVL更有效。 我决定testing这个说法:

  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> 

我很惊讶地发现安迪是多么的正确。 NVL解决scheme的成本要高出近50%。 因此,即使一个代码看起来不像另一个代码那样整洁或优雅,它可能会更有效率。 我多次运行这个程序,结果几乎每次都是一样的。 荣誉安迪…

在专家Oracle数据库架构中,我看到:

 WHERE DECODE(MYCOLUMN, SEARCHVALUE, 1) = 1 

我不知道这是否简单,但我偶尔使用

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

用一些对列types有效的值replace“-1”,但不可能在数据中真正find。

注:我使用MS SQL,而不是Oracle,所以不知道“ISNULL”是否有效。

使用NVL将nullreplace为双方的一些虚拟值,如下所示:

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

另一种替代方法,从执行的查询angular度来看可能是最优的, 只有当你正在做某种查询生成时 ,它才会有用,就是根据search值生成你需要的确切查询。

伪代码如下。

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

如果可能带外值:

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

这也可以在Oracle中完成。

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

在某些情况下,它用OR来击败IS NULLtesting。

我也很惊讶,DECODE让你检查NULL对NULL。

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

尝试

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

我们发现自己在使用驱动报告的Oraclefunction方面遇到了很多困难。 我们希望允许用户input一个值来限制结果,或者留空以返回所有logging。 这是我用过的,它对我们来说工作得很好。

 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) 

我会认为你有什么是可以的。 你也许可以使用:

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