oralce中exists not exists in not in对于NULL的处理

1.   先讨论 in 与 not in中存在NULL的情况, sql语句如下:

 1 select 1 result1 from dual where 1 not in (2, 3);
 2 
 3 
 4 select 1 result2 from dual where 1 not in (2, 3, null);
 5 
 6 
 7 select 1  result3 from dual where 1  in (2, 3, null, 1);
 8 
 9 
10 select 1 result4 from dual where 1  in (2, 3, null);

 

      执行结果:

result1 result2 result3 result4
1 没有任何返回值 1 没有任何返回值

 

      说明:innot in 会跟括号里面的值进行比较是否相等从而得出判断结果,而在oracle中null是无法进行比较的,只能进行判断IS NULL和IS NOT NULL,这就导致in和not in中与null进行比较时会返回false.  a in (b, c, d)相当于(a == b) || (a == c) || (a == d), 而 a not in (b, c, d)则相当于(a != b) && (a != c) && (a != d)

  • result1返回结果1显而易见,1跟2和3相比都不相等, 类似于(1<>2) && (1<>3) 结果为true所以返回结果1
  • result2中(1<>2) && (1<>3) && (1<>NULL)前面两个都是true可最后1跟NULL进行比较为false,一招走错满盘皆输就是这个道理,最终结果为false,因此没有返回结果
  • result3中(1 == 2) || (1 == 3) || (1 == NULL) || (1 == 1)前面三个表达式都是false,但最后一个表达式为true最终结果也就为真了,因此返回1。
  • result4中(1 == 2) || (1 == 3) || (1 == NULL)三个表达式都为false, 最终结果也就为false了, 无任何结果集返回。

 

2.   再来看看exists与 not exists的例子

1 select 1 result5 from dual where not exists (select 1 from dual t where t.dummy=null);
2 
3 select 1 result6 from dual where exists (select 1 from dual t where t.dummy=null);

 

 


      执行结果:

result5 result6
1 没有任何返回值

      

      说明: exists与not exists相当于一种逻辑判断,exists 的本质就是返回一个布尔值,exists测试关联子查询是否有数据返回,如果有至少一行返回的话则exists判断为真返回true, not exists判断关联子查询是否没有数据返回, 如果没有数据返回则判断为真,返回true。

 

  • result5查询中由于NULL不能与任何值作比较,因此自然是不存在t.dummy=null了,关联查询返回结果集为空,not exists逻辑判断结果为true, 最终1被查询出来。
  • result6查询中存在t.dummy=null, 说不通,关联查询返回结果集为空, 逻辑判断结果为false, 最终外层查询没有任何结果集返回。

 

3.   最后看一个有挺有意思的查询,从csdn论坛上看的。

1 select 'true'  from dual where (1,2) not in ((2,3),(2,null));
2 
3 select 'true' from dual where (2,1) not in ((2,3),(2,null));
4 
5 select 'true' from dual where (2,1) not in ((2,3),(null,3));
6 
7 select 'true' from dual where (2,1) not in ((2,3),(null,1));

     

      说明:二元值not in判断,... where (a, b) not in ((c, d), (e, f))类似于((a, b) != (c, d) ) &&  ((a, b) != (e, f)),将(a, b)与(c, d)比较看成坐标比较,只要有一个坐标对不上这个就是不相等的,因此上面的式子可以扩展成为 (a != c || b != d)  &&  (a != e || b != f)

  • 第1行的查询判断为true && true 结果为true、最终字符'true'得以返回。
  • 第3行的查询判断为true && false 结果为false、最终没有结果返回。
  • 第5行的查询判断为true && true 结果为true、 最终字符'true'得以返回。
  • 第7行的查询判断为true && false 结果为false、 最终没有结果返回。

 

4.    稍微总结一下:

  • in 在a in (b, c, d, ... , null)中, 括号里面的比较值里面存在NULL的话, 看其它比较值里面是否有跟a相等的值存在, 如果有则返回true, 否则返回false.
  • not in 在 a not in (b, c, d,..., null)中,如果括号里面存在NULL的话, 则一律返回false.
  • exists 在 exists的关联查询条件里面如果存在NULL的话,则内部查询是查询不出结果的,不符合exists至少有一行结果集返回的判断, 因此返回false.
  • not exists 在not exists的关联查询条件里面如果存在NULL的话,则内部查询也是查询不出结果的,符合not exists对于没有结果集返回的预期判断, 因此返回true.

 

5.    以上是个人的一些观点总结,欢迎大家批评指教。

posted @ 2014-09-25 10:12  tarbitrary  阅读(2761)  评论(0编辑  收藏  举报