多层次子查询的sql执行顺序的问题[转]


SQL里面嵌套子查询这是非常普遍的写法。
下面是有关子查询的一些说明:
子查询又称内部查询,而包含子查询的语句称之外部查询(又称主查询)。
所有的子查询可以分为两类,即相关子查询和非相关子查询。
非相关子查询是独立于外部查询的子查询,子查询总共执行一次,执行完毕后将值传递给外部查询。
相关子查询的执行依赖于外部查询的数据,外部查询执行一行,子查询就执行一次。
 
这个解释没问题,但是上周碰到个问题,2层子查询,其中相关子查询作为内层子查询,外层的是非相关的。这样的子查询到底算相关还是非相关呢?
 
 
select a.pro_name, a.pro_type, a.pro_price
  from supmka a, supmkb_1 b
 where a.pro_name = b.pro_name
   and a.pro_type = b.pro_type
   and a.pro_price = (select     d.pro_price
                        from( select  distinct   c.pro_price
                                from supmkb_2 c
                               where c.pro_no = b.pro_no) d
                       where rownum = 1);
 
红色标注的子查询是相关的(内层的表c和主查询的表b关联),而外层蓝色的是非相关的。
查看执行计划之后,发现优化器先做的红色部分的查询,然后再做蓝色,再做关联。也就是说,红色部分的 c.pro_no = b.pro_no,优化器忽略了(版本是Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
这样的数据查出来肯定有问题。
 
如果把distinct的位置换一下,
select a.pro_name, a.pro_type, a.pro_price
  from supmka a, supmkb_1 b
 where a.pro_name = b.pro_name
   and a.pro_type = b.pro_type
   and a.pro_price =  (select   distinct   d.pro_price
                        from ( select    c.pro_price
                                from supmkb_2 c
                               where c.pro_no = b.pro_no)  d
                       where rownum = 1);
优化器会先做关联查询。把 c.pro_no = b.pro_no 条件带进去做查询了。

所以大家不要写这种关联嵌套非关联的子查询,优化器都不知道怎么处理了。

另外在做实验期间,还发现一个问题:
在Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 上执行
select a.pro_name, a.pro_type, a.pro_price
  from supmka a, supmkb_1 b
 where a.pro_name = b.pro_name
   and a.pro_type = b.pro_type
   and a.pro_price =  (select     d.pro_price
                        from ( select  distinct   c.pro_price
                                from supmkb_2 c
                               where c.pro_no = b.pro_no)  d
                       where rownum = 1);
会报ora-00904,b.pro_no字段没有定义的错误。也就是说,优化器还是先执行了红色部分的SQL,但是并没有把where c.pro_no = b.pro_no条件忽略,导致了00904的错误。
而在 10.2.0.1.0 版本上,优化器直接忽略了where c.pro_no = b.pro_no条件。

实际上这个SQL写得非常不好。zizi只是抱着一种蛋疼的精神分析了一下SQL执行顺序,也算打发无聊的时间吧


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM