這裏的in後面的句子能夠理解爲or拼接,簡單舉例即函數
in (9566,9839,null)能夠等價於mgr=9566 or mgr=9839 or mgr=null,索引
not in (9566,9839,null)能夠等價於not(mgr=9566 or mgr=9839 or mgr=null)或mgr!=9566 and mgr!=9839 and mgr!=null。hash
爲何都是or拼接,in能夠而not in不能夠呢,能夠把not in理解爲後面的and表達式就知道了,由於mgr=null爲null,也就至關於false,致使整個表達式爲false,不管傳何值都爲false,天然沒法返回數據。select
當發現not in後的子查詢後面有null值時,能夠在子查詢裏用is not null或函數過濾null值。數據
正如所看到的,not in出現了不指望的結果集,存在邏輯錯誤。若是看一下上述兩個select 語句的執行計劃,也會不一樣,後者使用了hash_aj,因此,請儘可能不要使用not in(它會調用子查詢),而儘可能使用not exists(它會調用關聯子查詢)。若是子查詢中返回的任意一條記錄含有空值,則查詢將不返回任何記錄。若是子查詢字段有非空限制,這時可使用not in,而且能夠經過提示讓它用hasg_aj或merge_aj鏈接。查詢
若是查詢語句使用了not in,那麼對內外表都進行全表掃描,沒有用到索引;而not exists的子查詢依然能用到表上的索引。因此不管哪一個表大,用not exists都比not in 要快。
錯誤