時常我們在下查詢語法時,會先由A表中抓出鎖定的ID作為篩選B表時的IN條件下的選項
SELECT B1,B2,B3
FROM Table_B
WHERE B2 in (SELECT A1 FROM Table_A)
由Table_A抓出的A1欄位作為查詢Table_B的選項
一般來講這樣寫還滿直觀也看起來正確,如果A1欄位中的資料都是正常且有值的
也不會發現這段語法可能會發生的錯誤
舉例
SELECT ID,Name
FROM User
WHERE ID in (1,2,4,8)
-->很平常的就抓出User ID為1,2,4,8的資料列出來,也不會發生錯誤
當改成
SELECT ID,Name
FROM User
WHERE ID in (1,2,4,null)
-->也很正常的抓出ID為1,2,4以及null的資料
但如果是改成逆向查詢NOT IN時
SELECT ID,Name
FROM User
WHERE ID not in (1,2,4)
-->很正常的抓出ID不為1,2,4的資料列
此時加入null值
SELECT ID,Name
FROM User
WHERE ID not in (1,2,4,null)
-->一般會認為,就不要抓出1,2,4以及null的資料就好,但出來的結果卻是0筆資料
這到底是為什麼了?
這是因為在IN的語法中的運算轉換是根據下面所示
ID in (1,2,4,null)-->(ID=1 or ID=2 or ID=4 or ID=null)
只要其中一個符合就能抓出來
而如果改成Not in
ID not in (1,2,4,null)-->(ID <> 1 and ID <> 2 and ID <> 4 and ID <> null)
所有資料將被濾掉
原因
根據邏輯上的德摩根定律
~(A and B)-->~A or ~B
~(A or B)-->~A and ~B
所以在使用別張資料表的特定欄位作為篩選的選項時
要特別注意到IN後面的資料是否會有null存在
看是要在哪一個步驟中做防呆或轉換的工作來避免最後沒有資料被篩選出來
留言列表