SQL NULL值比較陷阱

SQL NULL值比較陷阱

起因:在與其他系統對接時,他們要下發數據到table表,下發邏輯爲如果A字段的值不是“XXX”和“YYY”就不會下發這條數據,因爲之前是沒有下發A字段,所以A字段的值一直都是NULL,但是查了數據庫還存在"“的,也就是A字段的值現在是存在NULL、”"、“XXX”、“YYY"四種情況,下端的業務邏輯根據下發的字段值要進行部分調整,如果A的值不是"XXX"和"YYY"就不能進行保存,所以在後端要進行邏輯判斷,查詢當前工單A字段的值是否爲"XXX"和"YYY”,
筆者的做法是:
SELECT 1 FROM table WHERE A <> 'XXX' AND A <> 'YYY'
如果查到數據爲空就正常保存,如果查出來有數據就就進行報錯之後回滾。
但是明明爲A字段爲NULL 的數據在保存的時候正常保存了,於是對SQL單獨執行之後發現了問題,通過百度大法得知這個現象學名是NULL值陷阱,如果字段值W爲空字符串就不會出現此問題,要規避此問題最簡單的就是加上<>NULL的判斷了,於是把SQL改成

SELECT 1 FROM table WHERE (A IS NOT NULL AND A <> 'XXX' AND A <> 'YYY')  OR A IS NULL

當然這個是最簡單粗暴的方法,看到有其他網友的解決方法還存在

SELECT * FROM some_table WHERE nvl(field1, null_if_value)=nvl(field2, null_if_value)

NVL函數是Oracle的一個空值轉換函數,相當於mysql的IFNULL

NVL(表達式1,表達式2)

如果表達式1爲空值,NVL返回值爲表達式2的值,否則返回表達式1的值。
原理就是用一個控制轉換函數把NULL轉換成別的字符串來和目標值進行比較
NVL()是oracle數據庫中的函數
IFNULL()是mysql數據庫中的函數
mysql版本就是

SELECT 1 FROM table WHERE IFNULL(A,'') <>'XXX' AND IFNULL(A,'') <> 'YYY'

希望大家在開發中儘量規避這些問題

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