Oracle Null与in,exists的关系说明(not in 查不到结果)(二)

2014-11-24 11:52:03 · 作者: · 浏览: 2
操作,而NOT IN 功能上相当于 !=ALL 的操作。

IN在逻辑上实际上就是对给定的成员集合或者子查询结果集进行逐条的判定.
如:select * from t1 where id in(1,2,3,NULL);

实际执行的命令等价于:
Select * from t1 where id=1 or id=2 orid=3 or id=NULL;

根据上面的表,Id=NULL 为UNKNOWN。 那么无法查询出列值为Null的记录。即等价于:
Select * from t1 where id=1or id=2 or id=3


NOT IN 的逻辑关系可以理解为:NOT (X=Y OR N=M) 等价于 X!=Y AND N!=M。那么:
select * fromt1 where id not in (1,2,3,NULL);

等价于
Select * fromt1 where id !=1 and id!=2 and id !=3 and id !=NULL

根据上面的NULL 表,id!=NULL 的结果为UNKNOWN。 那么该值为假,所以不管前面的条件真假与否,整个逻辑判断为假,所以没有返回任何记录。

解决方法就是在in 和not in的操作之前先把NULL 过滤掉。


2.3 EXISTS 说明

先看看exists 的执行过程:
select * from t1 where exists ( select * from t2 where t2.col1 = t1.col1)

相当于:

for x in ( select * from t1 )
loop
if ( exists ( select * from t2 where t2.col1 = x.col1))
then
OUTPUT THE RECORDin x
end if
end loop

exists ( select * from t2 where t2.col1 = x.col1)返回是一个布尔值,not exists只是对exists子句返回对布尔值取非,这与in和not in是有本质区别的(not in是对in表达式取非,转换成另一种等价表达式)

从上面的逻辑,也可以看出EXISTS语句实际上是通过循环外部查询的结果集,来过滤出符合子查询标准的结果集。于是外部查询的结果集数量对该语句执行性能影响最大,故如果外部查询的结果集数量庞大,用EXISTS语句的性能也不一定就会好很多。

但使用exists 一个很明显的优点,就是如果相关字段有索引的化,会使用索引来进行操作。而不需要进行全表扫描。 当表大的时候,效率肯定是会比in 和not in 高。这也是我们在写SQL 时推荐使用exists的原因。


现在看一下我们之前使用not in 查不到结果,但用not exits 却可以查到:

SQL>select empno,ename from emp A where not exists ( SELECT * FROM emp1 Bwhere B.job = A.job);

EMPNO ENAME
--------------------
8888 Dave

Dave的记录 存在与emp 表,不存在emp1表。

我们上边的查询等价于:
for x in ( select * from empA )
loop
if (not exists ( select * from emp2B where B.job = x.job )
then
OUTPUT THE RECORDin x
end if
end loop

这样当我们的X.job 为NULL 时,满足条件,输出了Dave 的记录。

作者“David Dai Oracle 笔记”