`
ludo2008
  • 浏览: 11141 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

oracle in和exists的详解分析

 
阅读更多

首先我要感谢aa和Liu Xing帮我发现了我日志中的错误。之前比较粗心,把3条SQL语句写成一样的了,对于给读者造成的麻烦,我深表抱歉。

今天我把原文做了修订,为了对得起读者对我的关注,我重新深入的研究了这个问题,在后面,我会把来龙去脉写清楚。

问题:

语句1

Select * from table1A where A.col1 not in ( select col1 from table2B)

转载注明出处:http://x- spirit.iteye.com/、http: //www.blogjava.net/zhangwei217245/
如果这样,本来应该有一条数据,结果没有。
如果我改写成这样:

语句2

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

结果就正确,有一条数据显示。
转载注明出处:http://x- spirit.iteye.com/、http: //www.blogjava.net/zhangwei217245/

经过一番搜索,原以为是子查询结果集太大的原因。

后来有网上强人指点:子查询里面有空集。即子查询的结果集里面有NULL的结果。

把查询语句修改成:

语句3

Select * from table1A where A.col1 not in ( select col1 from table2B 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 table1A WHERE A.col1 in ( 20 , 50 , NULL );

实际上就是执行了

SELECT * FROM table1A 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 table1A WHERE A.col1 not in ( 20 , 50 , NULL )

等价于

SELECT * FROM table1A 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 table1A WHERE A.col1 in ( SELECT B.col1 FROM table2B) OR A.col1 IS NULL ;


转载注明出处:http://x- spirit.iteye.com/、http: //www.blogjava.net/zhangwei217245/

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
OUTPUTTHERECORD in x
end if
end loop

转载注明出处:http://x- spirit.iteye.com/、http: //www.blogjava.net/zhangwei217245/
也就是说,EXISTS语句实际上是通过循环外部查询的结果集,来过滤出符合子查询标准的结果集。于是外部查询的结果集数量对该语句执行性能影响最大,故如果外部查询的结果集数量庞大,用EXISTS语句的性能也不一定就会好很多。
转载注明出处:http://x- spirit.iteye.com/、http: //www.blogjava.net/zhangwei217245/
当然,有人说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
OUTPUTTHERECORD in x
end if
end loop

转载注明出处:http://x- spirit.iteye.com/、http: //www.blogjava.net/zhangwei217245/
由于表A中不包含NULL的记录,所以,遍历完表A,也只能挑出表A中独有的记录。

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

分享到:
评论

相关推荐

    oracle中exists_和in的效率问题详解

    Oracle 中 EXISTS 和 IN 的效率问题详解 EXISTS 和 IN 都是 Oracle 中的集合操作符,但它们在使用和执行效率上有所不同。本文将深入探讨 EXISTS 和 IN 的使用场景、执行机制和效率问题。 EXISTS 的使用场景和机制 ...

    oracle数据库关于exists使用

    ### Oracle数据库中Exists与In的使用详解 #### 一、Exists 的使用方法 在Oracle数据库中,`EXISTS` 是一种常用的子查询操作符,用于判断子查询是否有结果返回。如果子查询至少返回一行数据,则 `EXISTS` 表达式的...

    “exists”和“in”的效率问题

    ### "Exists"与"In"的效率问题详解 #### 引言 在数据库查询语言SQL中,“Exists”与“In”是两种常用的子查询方法,它们在实际应用中各有优势与局限。本文将深入探讨这两种方法的工作原理、应用场景以及性能差异,...

    Oracle语句规划详解

    ### Oracle语句规划详解 #### 一、Oracle语句优化的重要性 在数据库管理与开发过程中,优化Oracle SQL语句对于提升系统的整体性能至关重要。优化不仅仅意味着更快的数据查询速度,还能减少资源消耗,提高数据库...

    oracle数据泵详解

    ### Oracle 数据泵详解 #### 一、EXPDP和IMPDP使用说明 Oracle Database 10g引入了数据泵(Data Pump)技术,这是一种用于在Oracle数据库间高效传输数据的新技术。数据泵技术主要包括两个工具:EXPDP(Export Data...

    oracle中not exists对外层查询的影响详解

    4. 分析和优化子查询:确保子查询本身已经优化,避免全表扫描,减少I/O操作。 总之,`NOT EXISTS`在Oracle中的性能取决于多个因素,包括数据量、索引的存在、数据库版本以及查询结构。了解这些因素并针对性地优化...

    oracle初始化参数详解

    Oracle初始化参数是数据库管理系统...理解并适当地配置这些参数对于优化Oracle数据库的性能和稳定性至关重要。在调整参数时,应谨慎操作,并根据实际情况进行测试,以确保改动不会对数据库的正常运行造成负面影响。

    Oracle语句优化规则详解【技术文档】

    1. 使用 EXISTS 替代 IN:当子查询只关心是否存在匹配记录时,EXISTS通常比IN更高效。 2. 避免嵌套子查询:尽量将子查询转化为连接操作,减少子查询的层次,提升性能。 五、函数和表达式 1. 函数的使用:避免在索引...

    ORACLE初始化参数详解

    ### ORACLE 初始化参数详解 #### 一、概述 在Oracle 8i系统中,初始化参数是配置数据库行为的重要工具。这些参数控制了数据库的各种运行特性,包括但不限于性能优化、安全性设置、故障诊断等方面。本文将详细解读...

    oracle 数据泵详解

    oracle数据泵详解 Oracle 数据泵是 Oracle 10g 以后引入的一种数据迁移工具,可以方便我们把低版本的数据库数据向高版本的数据库迁移。下面是 Oracle 数据泵的详细介绍。 一、EXPDP 和 IMPDP 使用说明 EXPDP...

    oracle导入导出详解

    这两个工具是Oracle Data Pump技术的一部分,相较于传统的`exp`和`imp`,Data Pump具有更高的性能和更灵活的数据操作选项。 1. expdp(Export Data Pump) - 功能:expdp用于将数据库对象和数据导出到操作系统文件...

    ORACLE 物化视图 详解

    ### ORACLE 物化视图详解 #### 一、物化视图概述 在Oracle数据库中,物化视图(Materialized View)是一种特殊的数据库对象,它存储的是一个查询的结果集,可以理解为一个预计算的快照。物化视图主要用于提高报表...

    oracle函数详解[收集].pdf

    Oracle函数详解涵盖了从基础操作到复杂查询的各个方面,理解和熟练运用这些函数和操作对于有效管理Oracle数据库至关重要。无论是数据查询、数据更新还是数据统计,都有相应的SQL语句和函数支持,使得数据处理变得...

    oracle 性能调整 sql性能优化大全

    `in和exists的区别与SQL执行效率分析 - diction - 博客园.htm`探讨了这两个子查询操作符的性能差异。通常,EXISTS在处理大量数据时比IN更快,因为它只需检查是否存在匹配项,而无需返回实际值。 3. **SQL语句优化*...

    oracle性能优化技巧

    ### Oracle性能优化技巧详解 #### 一、Oracle优化器模式 在Oracle数据库中,优化器是决定查询执行计划的关键组件,其目标是最小化资源消耗并最大化查询性能。Oracle提供了三种主要的优化器模式:基于规则(RULE)...

    oracle函数详解

    根据提供的文件内容,可以看出文档主要涉及的是Oracle SQL的基础语法与函数使用详解。下面将对文档中的各个知识点进行详细的解释和扩展。 ### Oracle SQL基础语法与函数详解 #### 1. 基本运算符 在Oracle SQL中,...

    oracle操作文档

    ### Oracle 查询优化基本准则详解 #### 一、引言 在数据库系统中,尤其是在大型企业级应用中,Oracle 数据库因其稳定性和强大的功能被广泛使用。然而,随着数据量的增长和业务复杂性的增加,如何有效地优化 Oracle ...

Global site tag (gtag.js) - Google Analytics