关于一个"恒真(恒假)条件"与"NULL参与比较判断"共同作用引发的语句结果异常

看标题,自己也觉得有些拗口.
主要是两方面:
(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参与比较判断.

请使用浏览器的分享功能分享到微信等