多層次子查詢的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