Thursday, October 14 2004 12:00 PM
一個IN語句在功能上相當於
= ANY語句:
select
'true' from dual where null = ANY (null);
select
'true' from dual where (null,null) = ANY ((null,null));
select
'true' from dual where (1,null) = ANY ((1,null));
當你使用一個EXISTS等效形式的語句,SQL將會計算所有行,並忽略子查詢中的值。
select
'true' from dual where exists (select null from dual);
select
'true' from dual where exists (select 0 from dual where null is null);
IN
和EXISTS在邏輯上是相同的。IN語句比較由子查詢返回的值,並在輸出查詢中過濾某些行。EXISTS語句比較行的值,並在子查詢中過濾某些行。對於NULL值的情況,行的結果是相同的。
select
ename from emp where empno in (select mgr from emp);
select
ename from emp e where exists (select 0 from emp where mgr = e.empno);
然而當邏輯被逆向使用,即NOT IN 及NOT EXISTS時,問題就會產生:
select
ename from emp where empno not in (select mgr from emp);
select
ename from emp e where not exists (select 0 from emp where mgr =
e.empno
);
NOT IN
語句實質上等同於使用=比較每一值,如果測試爲FALSE或者NULL,結果爲比較失敗。例如:
select
'true' from dual where 1 not in (null,2);
select
'true' from dual where 1 != null and 1 != 2;
select
'true' from dual where (1,2) not in ((2,3),(2,null));
select
'true' from dual where (1,null) not in ((1,2),(2,3));
這些查詢不會返回任何一行。第二個查詢語句更爲明顯,即
1 != null
,所以整個WHERE都爲false。然而這些查詢語句可變爲:
select
'true' from dual where 1 not in (2,3);
select
'true' from dual where 1 != 2 and 1 != 3;
你也可以使用NOT IN查詢,只要你保證返回的值不會出現NULL值:
select
ename from emp where empno not in (select mgr from emp where mgr is not
null
);
select
ename from emp where empno not in (select nvl(mgr,0) from emp);
通過理解IN,
EXISTS, NOT IN,以及NOT EXISTS之間的差別,當NULL出現在任一子查詢中時,你可以避免一些常見的問題。
Scott Stephens已經在Oracle公司工作大於13年之久,他的工作領域包括技術支持,電子商務,市場開發,以及軟件開發。