關於一個"恆真(恆假)條件"與"NULL參與比較判斷"共同作用引發的語句結果異常

qdrzq發表於2014-08-20

看標題,自己也覺得有些拗口.
主要是兩方面:
(1)恆真(恆假)條件:
不少開發人員,為了拼接語句的便利,採用恆真(比如1=1)條件為基礎,拼接若干個and條件,這樣就可以不做判斷條件之前應該是where還是and,同樣道理,採用恆假(比如1<>1)條件為稽查,拼接若干個or條件,這樣就可以不做判斷條件前面應該是where還是or.
這種做法,在邏輯上是正確的.但有時候也會有問題.

(2)NULL參與比較判斷
大家知道,如果需要判斷是否為NULL,不能用=和<>,而是需要用is NULL或者is not NULL,或者用IsNULL函式將NULL轉換為一個非NULL的值之後再進行比較.如果用=或者<>,出現的情況極有可能與預想的不同.

下面這個例子(偽SQL語句,可惜精確的語句當時並未儲存),是兩個因素一起出現在一個語句中的異常現象.
select ...
from A,B,C
where A.f1=*B.f1
and ...
and ( (substr(A.f2,1,4)='abcd' and {此處省略幾個結果為true的關聯條件})
     or 1<>1
    )
場景是substr(A.f2,1,4)實際值是NULL.
如果去掉or 1<>1,則能查詢出結果,如果加上or 1<>1,就不能查詢出結果了.

對這個奇怪的現象,通過檢視執行計劃簡單分析了一下,去掉or 1<>1的情況下,經過了三次巢狀迴圈連線之後出現一次filter,而加上or 1<>1,經過了兩次巢狀迴圈連線,就出現filter,而另一次巢狀迴圈,是發生在filter之後.
總之,恆真(恆假)條件的有無,使執行計劃有所不同,而執行計劃的不同,又影響了語句的結果.

啟示:謹慎使用1=1或1<>1這種恆真恆假條件,謹慎對待NULL參與比較判斷.

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29512902/viewspace-1254885/,如需轉載,請註明出處,否則將追究法律責任。

相關文章