数据库——SQL中in,not in,exists, not exists的区别

来源:互联网 发布:历史数据库 英文 编辑:程序博客网 时间:2024/06/07 01:55

1.exist,not exist一般都是与子查询一起使用;In可以与子查询一起使 用,也可以直接in (a,b…..)

2.exist会针对子查询的表使用索引. not exist会对主子查询都会使用索引. in与子查询一起使用的时候,只能针对主查询使用索引. not in则不会使用任何索引. 注意,一直以来认为exists比in效率高的说法是不准确的。

问题描述:IN子查询时,子查询中字段在表中不存在时语句却不报错?当子查询中字段名在表中不存在时语句不会报错(会返父查询中所有的结果),如果大家不注意这点,在使用in语句进行批量删除时就可能悲剧了;当子查询中的字段名在父子表中都不存在时,才会报错

上述问题是因为在不使用表别名的前提下如果in子查询里字段在内表找不到就会去引用外表的

以下四条是我从其他地方看到的,贴出来给大家参考1.子表引用父表列,而自己没有,在子表有数据的情况下,返回所有非空键的父表记录,子表为空,则结果无2.子表引用父表属性,只有最外层子查询才能引用3.有前缀标识,按前缀,如果子表父表前缀一样,按4的规则4.如果无前缀标识唯一性,子查询表也有此字段,那么以局部子查询为准  如果前缀一样,子查询存在此字段,则以子查询表为准,否则以父表的为准为了避免这种问题有几个方法供大家参考:1.当需要用到in子查询时,先执行下in里面的子查询语句是否有误,如果误则进行相应修改2.使用表前缀(别名)才是硬道理in和exists的区别:其实我们区分in和exists主要是造成了驱动顺序的改变(这是性能变化的关键),如果是exists,那么以外层表为驱动表,先被访问,如果是IN,那么先执行子查询,所以我们会以驱动表的快速返回为目标,那么就会考虑到索引及结果集的关系了 ,另外IN是不对NULL进行处理。

3.exists的原理:
exists做为where 条件时,是先对where 前的主查询询进行查询,然后用主查询的结果一个一个的代入exists的查询进行判断,如果为真则输出当前这一条主查询的结果,否则不输出

如下: 表A ID NAME 1 A1 2 A2 3 A3 表B ID AID NAME 1 1   B1 2 2   B2 3 2   B3 表A和表B是一对多的关系 A.ID --> B.AID SELECT ID , NAME FROM A WHERE EXISTS (SELECT * FROM B WHERE A.ID = B.AID) 执行结果为 1 A1 2 A2 原因可以按照如下分析 SELECT ID , NAME FROM A WHERE EXISTS (SELECT * FROM B WHERE B.AID = 1) -->SELECT * FROM B WHERE B.AID = 1有值返回真所以有数据 SELECT ID , NAME FROM A WHERE EXISTS (SELECT * FROM B WHERE B.AID = 2) -->SELECT * FROM B WHERE B.AID = 2有值返回真所以有数据 SELECT ID , NAME FROM A WHERE EXISTS (SELECT * FROM B WHERE B.AID = 3) -->SELECT * FROM B WHERE B.AID = 3无值返回真所以没有数据 NOT EXISTS 就是反过来 SELECT ID , NAME FROM A WHERE NOT EXIST (SELECT * FROM B WHERE A.ID = B.AID) 执行结果为 3 A3

in和exists

in是把外表和内表作hash连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询。
一直以来认为exists比in效率高的说法是不准确的:
如果查询的两个表大小相当,那么用in和exists差别不大;
如果两个表中一个较小一个较大,则子查询表大的用exists,子查询表小的用in;

1.性能的考虑就按子大主小用exist,主大子小用in的原则就可以.2.写法的不同:  exist的where条件是:"......  where exist (select id ..... where a.id=b.id)";  in的where条件是: "...... where id in (select id .... where a.id=b.id)"

not in 和not exists

尽量不要使用not in(它会调用子查询),而尽量使用not exists(它会调用关联子查询)。
如果子查询中返回的任意一条记录含有空值,则查询将不返回任何记录。
如果子查询字段有非空限制,这时可以使用not in,并且可以通过提示让它用hasg_aj或merge_aj连接。

in和=

select name from student where name in ('zhang','wang','li','zhao');select name from student where name='zhang' or name='li' or name='wang' or name='zhao'两者结果是相同,in的字段也可以与其它字段建复合索引.比如:T1包含下面key, accountd,groupid.SELECT * FROM T1 a WHERE          a.groupid = 2001         AND a.accountid = 1001         AND a.key IN ('abc', 'def', 'ala');--上面的sql可以将accountid,key建成复合索引.

如果查询语句使用了not in,那么对内外表都进行全表扫描,没有用到索引;而not exists的子查询依然能用到表上的索引。所以无论哪个表大,用not exists都比not in 要快。

原创粉丝点击