“NOT_IN”與“NULL”的邂逅
轉自:http://space.itpub.net/11320622/viewspace-675486
今天處理了一個因“NOT IN”與“”導致的問題,值得思考和總結,記錄在此,供參考。(感謝John丟擲的問題)我們以的形式先再現一下這個問題,然後對其分析,最後給出幾種解決方案。
[@more@]1.建立實驗表T,並分別初始化三條資料,注意T2表中包含一條空(NULL)資料。
sec@ora10g> insert into t1 values (1);
sec@ora10g> insert into t1 values (2);
sec@ora10g> insert into t1 values (3);
sec@ora10g> insert into t2 values (1);
sec@ora10g> insert into t2 values (null);
sec@ora10g> insert into t2 values (3);
sec@ora10g> commit;
2.確認T1表和T2表的資料內容
sec@ora10g> select * from t1;
X
----------
1
2
3
sec@ora10g> select * from t2;
X
----------
1
3
3.再現問題嘗試使用“NOT IN”方法獲得不在T2表中出現的T1表資料。
sec@ora10g> select * from t1 where x not in (select x from t2);
no rows selected問題已重現,明明T1中的資料“2”在T2表中沒有,為什麼沒有返回結果呢?原因:當子查詢返回含有“NULL”記錄時,使用NOT IN時將不會有返回記錄。解析:可以這麼理解這個現象:Oracle中的NULL是一個不確定的狀態。以T1表中的記錄“2”為例,在與T2表中的NULL進行比較時,NULL既可以是“2”,也可以不是“2”,因為判斷不了他們的關係,所以只能返回空記錄,此乃無奈之舉。
4.為什麼使用“IN”可以返回“正確”的結果?
sec@ora10g> select * from t1 where x in (select x from t2);
X
----------
1
3這是顯然的,因為T2表中確確實實的存在著記錄“1”和記錄“3”,因此“1”和“3”被返回。不過,注意,NULL依然是一個不確定的狀態,因此在T1表中的“2”與NULL比較之後仍然是個不確定的結果,因此“2”是不會被返回的。這裡給我們的一個錯覺:T1表中的“2”與T2表中NULL不同(他們其實也可能相同)。
5.諸多解決方案
1)排除“NOT IN”子查詢中存在的NULL值
sec@ora10g> select * from t1 where x not in (select x from t2 where x is not null);
X
----------
2
2)使用“NOT”改寫
sec@ora10g> select * from t1 where not exists (select * from t2 where t1.x=t2.x);
X
----------
2
3)使用“外連線”改寫
sec@ora10g> select t1.* from t1, t2 where t1.x = t2.x(+) and t2.x is null;
X
----------
2道理是相通的,想想為什麼使用“NOT EXISTS”和“外連線”方法改寫後就可以成功?(給大家一個機會,這裡不贅述。)
6.小結這裡描述的的案例可以用“陷阱”來形容,不過對於這個“陷阱”我們是有諸多解決方案進行規避的。遇到問題在沉著、冷靜+淡定之後,終有柳暗花明之時。希望您也有思考之後豁然開朗之悅。
今天處理了一個因“NOT IN”與“”導致的問題,值得思考和總結,記錄在此,供參考。(感謝John丟擲的問題)我們以的形式先再現一下這個問題,然後對其分析,最後給出幾種解決方案。
[@more@]1.建立實驗表T,並分別初始化三條資料,注意T2表中包含一條空(NULL)資料。
sec@ora10g> insert into t1 values (1);
sec@ora10g> insert into t1 values (2);
sec@ora10g> insert into t1 values (3);
sec@ora10g> insert into t2 values (1);
sec@ora10g> insert into t2 values (null);
sec@ora10g> insert into t2 values (3);
sec@ora10g> commit;
2.確認T1表和T2表的資料內容
sec@ora10g> select * from t1;
X
----------
1
2
3
sec@ora10g> select * from t2;
X
----------
1
3
3.再現問題嘗試使用“NOT IN”方法獲得不在T2表中出現的T1表資料。
sec@ora10g> select * from t1 where x not in (select x from t2);
no rows selected問題已重現,明明T1中的資料“2”在T2表中沒有,為什麼沒有返回結果呢?原因:當子查詢返回含有“NULL”記錄時,使用NOT IN時將不會有返回記錄。解析:可以這麼理解這個現象:Oracle中的NULL是一個不確定的狀態。以T1表中的記錄“2”為例,在與T2表中的NULL進行比較時,NULL既可以是“2”,也可以不是“2”,因為判斷不了他們的關係,所以只能返回空記錄,此乃無奈之舉。
4.為什麼使用“IN”可以返回“正確”的結果?
sec@ora10g> select * from t1 where x in (select x from t2);
X
----------
1
3這是顯然的,因為T2表中確確實實的存在著記錄“1”和記錄“3”,因此“1”和“3”被返回。不過,注意,NULL依然是一個不確定的狀態,因此在T1表中的“2”與NULL比較之後仍然是個不確定的結果,因此“2”是不會被返回的。這裡給我們的一個錯覺:T1表中的“2”與T2表中NULL不同(他們其實也可能相同)。
5.諸多解決方案
1)排除“NOT IN”子查詢中存在的NULL值
sec@ora10g> select * from t1 where x not in (select x from t2 where x is not null);
X
----------
2
2)使用“NOT”改寫
sec@ora10g> select * from t1 where not exists (select * from t2 where t1.x=t2.x);
X
----------
2
3)使用“外連線”改寫
sec@ora10g> select t1.* from t1, t2 where t1.x = t2.x(+) and t2.x is null;
X
----------
2道理是相通的,想想為什麼使用“NOT EXISTS”和“外連線”方法改寫後就可以成功?(給大家一個機會,這裡不贅述。)
6.小結這裡描述的的案例可以用“陷阱”來形容,不過對於這個“陷阱”我們是有諸多解決方案進行規避的。遇到問題在沉著、冷靜+淡定之後,終有柳暗花明之時。希望您也有思考之後豁然開朗之悅。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/73920/viewspace-1041510/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【問題處理】“NOT IN”與“NULL”的邂逅Null
- 01_與bootstrap的初次邂逅boot
- 我與圖靈書的“邂逅”圖靈
- 與計算機行業的邂逅計算機行業
- not null與check is not nullNull
- mysql探究之null與not nullMySqlNull
- 那一年,與 Laravel 邂逅的初夏!Laravel
- Null 與 “” 的區別Null
- undefined與null與?. ??UndefinedNull
- MySQL案例-TIMESTAMP NOT NULL與NULLMySqlNull
- 與搭訕大師邂逅札記
- null與indexNullIndex
- NULL與索引Null索引
- null與substrNull
- NULL與排序Null排序
- undefined與null的區別UndefinedNull
- 面向協議程式設計與 Cocoa 的邂逅 (下)協議程式設計
- 面向協議程式設計與 Cocoa 的邂逅 (上)協議程式設計
- NULL 值與索引Null索引
- Oracle空串與null的處理OracleNull
- [資料結構與演算法] 邂逅棧資料結構演算法
- 初次邂逅 EasyExcelExcel
- NULL 值與索引(二)Null索引
- mysql中null與“空值”的坑MySqlNull
- python None與Null 的區別PythonNoneNull
- MySQL裡null與空值的辨析MySqlNull
- 理解:MySQL的null與空字串的不同MySqlNull字串
- 了不起的 “filter(NULL IS NOT NULL)”FilterNull
- Vue.js-邂逅Vue.js
- 邂逅VUE.JSVue.js
- 紅包雨中:Redis 和 Lua 的邂逅Redis
- ((NULL) null).printNULL();((NULL) null).printnull();Null
- MySQL中is not null和!=null和<>null的區別MySqlNull
- in、exists操作與null的一點總結Null
- oracle sql_not exists與null的測試OracleSQLNull
- 索引裡的NULL值與排序小記索引Null排序
- JavaScript undefined與null區別JavaScriptUndefinedNull
- count_sum_distinct與nullNull