中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

oracle sql優化中not in子句包含null返回結果為空的分析

發布時間:2021-11-11 13:39:19 來源:億速云 閱讀:269 作者:iii 欄目:關系型數據庫

這篇文章主要介紹“oracle sql優化中not in子句包含null返回結果為空的分析”,在日常操作中,相信很多人在oracle sql優化中not in子句包含null返回結果為空的分析問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”oracle sql優化中not in子句包含null返回結果為空的分析”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

創建測試表:

create table t_dept as select * from   scott.dept;

create table t_emp as select * from   scott.emp;

insert into t_emp(deptno,ename)  values(null,'MINGSHUO');   --在emp表中插入一條數據,deptno列為null

commit;

數據結構如下:

SQL> select distinct deptno from   t_emp;

 

      DEPTNO

----------

          30

 

          20

          10

SQL> select distinct deptno from   t_dept;

 

      DEPTNO

----------

          30

          20

          40

          10

 

此時發起一條查詢,查詢不在emp中但是在dept表中部門信息:

SQL> select * from t_dept where deptno   not in (select deptno from t_emp where deptno is not null);

 

      DEPTNO DNAME          LOC

---------- -------------- -------------

          40 OPERATIONS     BOSTON

 

此時是有結果返回的。

然后把子查詢中的where dept is not null去掉,再次運行查詢:

SQL> select * from t_dept where deptno   not in (select deptno from t_emp);

 

no rows selected

此時返回結果為空。

這里很多人存在疑惑,為什么子查詢結果集包括null就會出問題,比如t_dept.deptno為40的時候,40 not in (10,20,30,null)也成立啊。畢竟oracle查詢優化器不如人腦智能懂得變通,查看執行計劃就比較容易明白了。

Execution Plan

----------------------------------------------------------

Plan hash value: 2864198334

 

-----------------------------------------------------------------------------

| Id    | Operation          | Name   | Rows    | Bytes | Cost (%CPU)| Time       |

-----------------------------------------------------------------------------

|     0 | SELECT STATEMENT   |        |       4 |   172 |     5    (20)| 00:00:01 |

|*    1 |  HASH   JOIN ANTI NA |        |     4 |     172 |     5  (20)| 00:00:01 |

|     2 |   TABLE ACCESS FULL| T_DEPT   |     4 |   120 |       2   (0)| 00:00:01 |

|     3 |   TABLE ACCESS FULL|   T_EMP  |    15 |     195 |     2   (0)| 00:00:01 |

-----------------------------------------------------------------------------

 

Predicate Information (identified by   operation id):

---------------------------------------------------

 

     1 - access("DEPTNO"="DEPTNO")

 

Note

-----

     - dynamic sampling used for this statement (level=2)

 

注意到這里id 1是HASH JOIN ANTI NA。這時候就想起來了,not in是對null值敏感的。所以普通反連接是不能處理null的,因此oracle推出了改良版的能處理null的反連接方法,這種方法被稱為"Null-Aware Anti Join"。operation中的關鍵字NA就是這么來的了。

在Oracle 11gR2中,Oracl通過受隱含參數_OPTIMIZER_NULL_AWARE_ANTIJOIN控制NA,其默認值為TRUE,表示啟用Null-Aware Anti Join。

下面禁用掉,然后再觀察:

alter session set   "_optimizer_null_aware_antijoin" = false; 

再次執行:select * from t_dept where deptno   not in (select deptno from t_emp);

執行計劃如下:

Execution Plan

----------------------------------------------------------

Plan hash value: 393913035

 

-----------------------------------------------------------------------------

| Id    | Operation          | Name   | Rows    | Bytes | Cost (%CPU)| Time       |

-----------------------------------------------------------------------------

|     0 | SELECT STATEMENT   |        |       1 |    30 |     4     (0)| 00:00:01 |

|*    1 |  FILTER            |        |       |         |            |          |

|     2 |   TABLE ACCESS FULL| T_DEPT   |     4 |   120 |       2   (0)| 00:00:01 |

|*    3 |   TABLE ACCESS FULL|   T_EMP  |    14 |     182 |     2   (0)| 00:00:01 |

-----------------------------------------------------------------------------

 

Predicate Information (identified by   operation id):

---------------------------------------------------

 

     1 - filter( NOT EXISTS (SELECT 0 FROM "T_EMP"   "T_EMP" WHERE

                LNNVL("DEPTNO"<>:B1)))

     3 - filter(LNNVL("DEPTNO"<>:B1))

 

Note

-----

     - dynamic sampling used for this statement (level=2)

 

lnnvl用于某個語句的where子句中的條件,如果條件為true就返回false;如果條件為UNKNOWN或者false就返回true。該函數不能用于復合條件如AND, OR, or BETWEEN中。

此時比如t_dept.deptno為40的時候,(40 not in 10)and(40 not in 20)and(40 not in 30)and(40 not in null),注意這里是and“并且”,條件都需要滿足。

結果是true and true and true and false或者unknow。經過lvnnvl函數后:

false and false and false and true,結果還是false。所以自然就不會有結果了。

如果還不明白的話換個比較直觀的寫法:

SQL> select * from t_dept where deptno   not in (10,20,null);

 

no rows selected

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 719542577

 

----------------------------------------------------------------------------

| Id    | Operation         | Name   | Rows    | Bytes | Cost (%CPU)| Time       |

----------------------------------------------------------------------------

|     0 | SELECT STATEMENT  |        |       1 |    30 |     2     (0)| 00:00:01 |

|*    1 |  TABLE ACCESS FULL| T_DEPT   |     1 |    30 |       2   (0)| 00:00:01 |

----------------------------------------------------------------------------

 

Predicate Information (identified by   operation id):

---------------------------------------------------

 

     1 - filter("DEPTNO"<>10 AND   "DEPTNO"<>20 AND

                "DEPTNO"<>TO_NUMBER(NULL))

 

Note

-----

     - dynamic sampling used for this statement (level=2)

 

過濾條件"DEPTNO"<>10 AND "DEPTNO"<>20 AND "DEPTNO"<>TO_NUMBER(NULL)因為最后一個and條件,整個條件恒為flase或者unkonw。

所以not in的子查詢中出現null值,無返回結果。

這種時候其實可以用not exists寫法和外連接代替:

not exists寫法:

其實這種寫法前面已經出現過了。就在禁用掉反連接之后,出現在fileter中的,oracle在內部改寫sql時可能就采用了這種寫法:

select *

    from t_dept d

 where not exists (select 1 from t_emp e   where d.deptno = e.deptno);

外連接的寫法:

select d.* from t_dept d, t_emp e where   d.deptno=e.deptno(+) and e.deptno is null;

同事還給我展示了丁俊的實驗,里面有復合列的討論,結論簡單明了,這里我就直接搬過來吧,如下:

/**

根據NULL的比較和邏輯運算規則,OR條件有一個為TRUE則返回TRUE,全為FALSE則結果為FALSE,其他為UNKNOWN,比如

(1,2) not in (null,2)則相當于1 <> null or 2 <> 2,那么明顯返回的結果是UNKNOWN,所以不可能為真,不返回結果,但是

(1,2) not in (null,3)相當于1 <> null or 2 <> 3,因為2<>3的已經是TRUE,所以條件為TRUE,返回結果,也就說明了為什么Q2中的

測試是那樣的結果

**/

 

看個簡單的結果:

SQL> SELECT * FROM DUAL WHERE (1,2)   not in ( (null,2) );

 

DUMMY

-----

SQL> SELECT * FROM DUAL WHERE (1,2)   not in ( (null,3) );

 

DUMMY

-----

X

 

到此,關于“oracle sql優化中not in子句包含null返回結果為空的分析”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

东明县| 罗田县| 南投市| 鹤山市| 兴业县| 浦东新区| 建阳市| 双流县| 安福县| 濮阳县| 桐城市| 天峻县| 晋江市| 南岸区| 方正县| 兰州市| 江永县| 迁安市| 凤山县| 大宁县| 尤溪县| 北海市| 宜川县| 铁岭市| 如皋市| 高青县| 化州市| 上林县| 驻马店市| 中牟县| 商城县| 沂源县| 哈尔滨市| 常熟市| 平山县| 措勤县| 郁南县| 吉林省| 蒙自县| 山阴县| 霍山县|