SQL優化-IN和EXITS

INEXITS

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);
  通過理解
INEXISTSNOT IN,以及NOT EXISTS之間的差別,當NULL出現在任一子查詢中時,你可以避免一些常見的問題




not in 邏輯上不完全等同於not exists
請注意not in 邏輯上不完全等同於not exists,如果你誤用了not in,小心你的程序存在致命的BUG

請看下面的例子:
create table t1 (c1 number,c2 number);
create table t2 (c1 number,c2 number);

insert into t1 values (1,2);
insert into t1 values (1,3);
insert into t2 values (1,2);
insert into t2 values (1,null);

select * from t1 where c2 not in (select c2 from t2);
no rows found
select * from t1 where not exists (select 1 from t2 where t1.c2=t2.c2);
c1 c2
1 3

正如所看到的,not in 出現了不期望的結果集,存在邏輯錯誤。如果看一下上述兩個select語句的執行計劃,也會不同。後者使用了hash_aj
因此,請儘量不要使用
not in(它會調用子查詢),而儘量使用not exists(它會調用關聯子查詢)。如果子查詢中返回的任意一條記錄含有空值,則查詢將不返回任何記錄,正如上面例子所示。
除非子查詢字段有非空限制,這時可以使用
not in ,並且也可以通過提示讓它使用hasg_ajmerge_aj連接。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章