sql查询 not in 谨防陷阱
首先来说说Oracle中的NULL。
Oracle中的NULL代表的是无意义,或者没有值。将NULL和其他的值进行逻辑运算,运算过程中,NULL的表现更象是FALSE。
下面请看真值表:
AND NULL | OR NULL | |
---|---|---|
TRUE | NULL | TRUE |
FALSE | FALSE | NULL |
NULL | NULL | NULL |
语句1:
Select * from table1 A where A.col1 not in ( select col1 from table2 B )
如果这样,本来应该有一条数据,结果没有。
改写成这样:
语句2:
select * from table1 A where not exists (SELECT * FROM table2 B where B.col1 = A.col1)
结果就有数据了
原因是因为子查询里面有空集。即子查询的结果集里面有NULL的结果。
把查询语句修改成:
语句3
Select * from table1 A where A.col1 not in ( select col1 from table2 B where B.col1 is not null )
数据就查询出来了。
注:
in是一个成员条件, 对于给定的一个集合或者子查询,它会比较每一个成员值。
IN功能上相当于 =ANY 的操作,而NOT IN 功能上相当于 !=ALL 的操作。
IN在逻辑上实际上就是对给定的成员集合或者子查询结果集进行逐条的判定,例如:
SELECT * FROM table1 A WHERE A.col1 in (20,50,NULL);
实际上就是执行了
SELECT * FROM table1 A WHERE A.col1=20 OR A.col1=50 OR A.col1=NULL;
这样,根据NULL的运算特点和真值表,我们可以看出,上边这个WHERE 字句可以被简化(如果返回NULL则无结果集返回,这一点和FALSE是一样的)为
WHERE A.col1=20 OR A.col1=50
也就是说,如果你的table1中真的存在含有NULL值的col1列,则执行该语句,无法查询出那些值为null的记录。
再来看看NOT IN。根据逻辑运算关系,我们知道,NOT (X=Y OR N=M) 等价于 X!=Y AND N!=M,那么:
SELECT * FROM table1 A WHERE A.col1 not in (20,50,NULL)
等价于
SELECT * FROM table1 A WHERE A.col1!=20 AND A.col1!=50 AND A.col1!=NULL
备注:个人博客同步至简书。
网友评论