问题:

语句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  ) 


果然就查出来了。而且一点不差。。。厉害阿~~~

下面是针对本文题的分析:

1。 首先来说说Oracle中的NULL。

Oracle中的NULL代表的是无意义,或者没有值。将NULL和其他的值进行逻辑运算,运算过程中,NULL的表现更象是FALSE。
下面请看真值表:

   AND NULL  OR NULL
 TRUE  NULL  TRUE
 FALSE  FALSE  NULL
 NULL  NULL  NULL

另外,NULL和其他的值进行比较或者算术运算(<、>、=、!=、+、-、*、/),结果仍是NULL。

如果想要判定某个值是否为NULL,可以用IS NULL或者IS NOT NULL。

2. 再来说说Oracle中的IN。

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

根据NULL的运算特性和真值表,该语句无论前两个判定条件是否为真,其结果一定是NULL或者FALSE。故绝对没有任何记录可以返回。

这就是为什么语句1 查不到应有结果的原因。当然,如果你用NOT IN的时候,预先在子查询里把NULL去掉的话,那就没问题了,例如语句3 。
有些童鞋可能要问了:那如果我想把A表里面那些和B表一样col1列的值一样的记录都查出来,即便A、B两表里面的col1列都包括值为NULL的记录的 话,用这一条语句就没办法了吗?

我只能很遗憾的告诉你,如果你想在WHERE后面单纯用IN 似乎不太可能了,当然,你可以在外部的查询语句中将NULL条件并列进去,例如:

SELECT   *   FROM  table1 A  WHERE  A.col1  in  ( SELECT  B.col1  FROM  table2 B)  OR  A.col1  IS   NULL ;

3. 最后谈谈EXISTS。

有人说EXISTS的性能比IN要好。但这是很片面的。我们来看看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 RECORD in x
       end   if 
end  loop

也就是说,EXISTS语句实际上是通过循环外部查询的结果集,来过滤出符合子查询标准的结果集。于是外部查询的结果集数量对该语句执行性能影响最大,故 如果外部查询的结果集数量庞大,用EXISTS语句的性能也不一定就会好很多。
当然,有人说NOT IN是对外部查询和子查询都做了全表扫描,如果有索引的话,还用不上索引,但是NOT EXISTS是做连接查询,所以,如果连接查询的两列都做了索引,性能会有一定的提升。
当然至于实际的查询效率,我想还是具体情况具体分析吧。

那么我们不妨来分析一下语句2为什么能够的到正确的结果吧:

语句2是这样的:

select   *   from table1 A where   not   exists  ( SELECT B.col1 FROM table2 B where B.col1 = A.col1)

实际上是这样的执行过程:

for  x  in  (  select   *   from table1 A )
   loop
       if  (not exists  (  select * from table2 B where B.col1 =  x.col1 )
       then 
         OUTPUT THE RECORD in x
       end   if 
end  loop

由于表A中不包含NULL的记录,所以,遍历完表A,也只能挑出表A中独有的记录。

这就是为什么语句2 能够完成语句3 的任务的原因。

但如果表A中存在NULL记录而表B中不存在呢?
答案:A表中的NULL也会被查出来。因为select * from table2 B where B.col1 = NULL不返回结果,故
not exists ( select * from table2 B where B.col1 = x.col1 )的值为真。

转://Oracle not in查不到应有的结果(NULL、IN、EXISTS详解)的更多相关文章

  1. 问题:oracle select into;结果:oracle SELECT INTO 和 INSERT INTO SELECT 两种表复制语句详解

    oracle SELECT INTO 和 INSERT INTO SELECT 两种表复制语句详解 (2011-07-08 08:59:47) 转载▼ 标签: it 分类: oracle 我们经常会遇 ...

  2. 全网最详细的Windows系统里Oracle 11g R2 Database(64bit)的完全卸载(图文详解)

    不多说,直接上干货! 前期博客 全网最详细的Windows系统里Oracle 11g R2 Database(64bit)的下载与安装(图文详解) 若你不想用了,则可安全卸载. 完全卸载Oracle ...

  3. oracle 12c创建可插拔数据库(PDB)与用户详解

    前言 由于oracle 12c使用了CDB-PDB架构,类似于docker,在container-db内可以加载多个pluggable-db,因此安装后需要额外配置才能使用. 一.修改listener ...

  4. oracle SELECT INTO 和 INSERT INTO SELECT 两种表复制语句详解

    我们经常会遇到需要表复制的情况,如将一个table1的数据的部分字段复制到table2中,或者将整个table1复制到table2中,这时候我们就要使用SELECT INTO 和 INSERT INT ...

  5. Netsuite Formula > Oracle函数列表速查(PL/SQL单行函数和组函数详解).txt

    PL/SQL单行函数和组函数详解 函数是一种有零个或多个参数并且有一个返回值的程序.在SQL中Oracle内建了一系列函数,这些函数都可被称为SQL或PL/SQL语句,函数主要分为两大类: 单行函数 ...

  6. Oracle权限管理详解

    Oracle权限管理详解 转载--CzmMiao的博客生活 Oracle 权限 权限允许用户访问属于其它用户的对象或执行程序,ORACLE系统提供三种权限:Object 对象级.System 系统级. ...

  7. ORACLE PL/SQL编程详解

    ORACLE PL/SQL编程详解 编程详解 SQL语言只是访问.操作数据库的语言,并不是一种具有流程控制的程序设计语言,而只有程序设计语言才能用于应用软件的开发.PL /SQL是一种高级数据库程序设 ...

  8. Oracle数据字典详解

    学习笔记:oracle数据字典详解 --- 本文为TTT学习笔记,首先介绍数据字典及查看方法,然后分类总结各类数据字典的表和视图.然后列出一些附例.   数据字典系统表,保存在system表空间中. ...

  9. 53个Oracle语句优化规则详解(转)

    Oracle sql 性能优化调整  1. 选用适合的ORACLE优化器        ORACLE的优化器共有3种:a. RULE (基于规则)   b. COST (基于成本) c. CHOOSE ...

随机推荐

  1. Vue项目build打包部署到Tomcat后,刷新报404错误解决方案

    问题描述: 一.更新依赖,并打包项目 cd /root/.jenkins/workspace/v-test;npm installcd /root/.jenkins/workspace/v-test; ...

  2. 汇编语言--微机CPU的指令系统(五)(循环指令)

    (8)循环指令 循环结构是程序的三大结构之一.为了方便构成循环结构,汇编语言提供了多种循环指令,这些循环指令的循环次数都是保存在计数器CX或ECX中.除了CX或ECX可以决定循环是否结束外,有的循环指 ...

  3. react学习(四)之设置 css样式 篇

    react中设置css样式 方法一: 行内样式:使用{{  }},与正常jsx中插入js代码不一样,这里需要两个括号. <div style={ { float: 'right',} }> ...

  4. HDU3038(KB5-D加权并查集)

    How Many Answers Are Wrong Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  5. hihoCoder编程练习赛52

    题目1 : 字符串排序 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 一般我们在对字符串排序时,都会按照字典序排序.当字符串只包含小写字母时,相当于按字母表" ...

  6. layui layer select 选择被遮挡

    在编程的时候, layer弹窗中的select 经常会遇到被遮挡的情况: 解决方法:在页面里面找到对应div的class 给overflow新的属性visible即可(默认值.内容不会被修剪,会呈现在 ...

  7. 小tips:Hbuilder编辑器开启less自动编译为css的方法

    1.首先,依次打开菜单栏->工具->预编译器设置,打开后是这样的: 2.然后点击新建. 3.文件后缀为.less触发命令地址就是lessc.cmd所在的地址,先用npm全局安装less, ...

  8. Human Motion Analysis with Wearable Inertial Sensors——阅读2

    Human Motion Analysis with Wearable Inertial Sensors 实时人体运动跟踪已经应用于生物医学领域的许多应用:临床步态分析,运动康复,跌倒检测,关节生物力 ...

  9. Python 一键commit文件、目录到SVN服务器

    一键commit文件.目录到SVN服务器   by:授客 QQ:1033553122 实现功能 1 测试环境 1 代码show 1   实现功能 一键提交文件.目录到svn 测试环境 Win7 64位 ...

  10. 不能用notepad++编辑器编写python

    不能用notepad++编辑器编写python,因为notepad对空格支持不是很良好,会出现莫名其妙的错误!建议用vim或emacs. 有人这样解释:不要混合使用制表符和空格来缩进,因为这在跨越不同 ...