posts - 262,  comments - 221,  trackbacks - 0

          一、級聯數據的表示:

          首先我們來看一張關于組織架構的結構圖




          這張圖是一個典型的“樹型結構圖”,只有一個根節點(King),其下有若干個分支節點,每個分支節點下又有若干個子節點或樹葉節點。假如我們要把這些關系信息映射到數據庫中(此處以Oracle9i數據庫為例),表結構應當如何表示呢?

          CREATE TABLE EMPLOYEE (

          EMP_ID          
          NUMBER (4CONSTRAINT EMP_PK PRIMARY KEY,

          FNAME           
          VARCHAR2 (15)NOT NULL

          LNAME           
          VARCHAR2 (15)NOT NULL

          DEPT_ID         
          NUMBER (2)NOT NULL,

          MANAGER_EMP_ID  
          NUMBER (4CONSTRAINT EMP_FK REFERENCES EMPLOYEE(EMP_ID),

          SALARY          
          NUMBER (7,2)NOT NULL,

          HIRE_DATE       DATENOT 
          NULL

          JOB_ID          
          NUMBER (3));

          請注意這里紅色粗體部分,字段MANAGER_EMP_ID的值引用了字段EMP_ID的值,我們稱這種引用為“自引用”。它規定了經理人員的ID必須是來自表中存在的員工ID。

          二、Oracle 9i中的start with...connect by:

          [[START WITH condition1]  CONNECT BY condition2]

          START WITH condition1
          指定級聯數據的根記錄(一條或多條),所有滿足條件1的記錄都將被當成是根紀錄,假如我們不給定START WITH子句,所有的紀錄都會被當成是根紀錄,通常這不是我們想要的結果。condition1可以是一個子查詢。

          CONNECT BY condition2
          指定級聯數據中父紀錄和子紀錄之間的關系,這里的關系被表示成一個表達式,當前紀錄的字段會和對應的父紀錄的某個字段進行比較。condition2必須跟著一個PRIOR操作符,該操作符用于標明父紀錄的字段。condtion2不能包含子查詢

          PRIOR是Oracle的一個內建操作符,僅用于級聯查詢。當我們在級聯查詢的CONNECT BY條件中使用了PRIOR操作符時,位于其后的表達式被當成是當前紀錄的父紀錄進行比較。

          三、實例比較:

          下面我們通過2條SQL語句來演示如何進行級聯查詢,以及PRIOR在不同位置時帶來的不同結果。

          SQL> select * from employee;

                  ID EMP_NAME             MANAGER_ID
          ---------- -------------------- ----------
                   1 king
                   
          2 mark                          1
                   
          3 bob                           1
                   
          4 tom                           2
                   
          5 paul                          2
                   
          6 jack                          3
                   
          7 ben                           4

          7 rows selected.

          需求:我們要找出員工ID為2的人及其所有下屬(包括直接和間接下屬)
          SQL> select * from employee start with id = 2 connect by prior id = manager_id order by id;

                  ID EMP_NAME             MANAGER_ID
          ---------- -------------------- ----------
                   2 mark                          1
                   
          4 tom                           2
                   
          5 paul                          2
                   
          7 ben                           4

          請注意PRIOR操作符被放置在字段ID前面。查詢結果中ID為7的員工ben,雖然其對應的經理ID為4,但是因為員工號為4的tom,其對應的經理ID為2,所以ben是屬于mark的間接下屬而符合查詢條件。

          我們已經知道PRIOR放在那一側,那一側的字段就會被當成父記錄的字段而被用于和當前記錄的字段(另一側的表達式)進行比較,那么假如我們把PRIOR放在manager_id一側,結果會有什么不同嗎?請看下面的SQL執行結果。
          SQL> select * from employee start with id = 2 connect by id = prior manager_id order by id;

                  ID EMP_NAME             MANAGER_ID
          ---------- -------------------- ----------
                   1 king
                   
          2 mark                          1

          很明顯結果完全不同,那么是什么造成了兩次查詢的結果完全不同呢?說到這里我們還要再回到SQL語言本身,我用一種比較直白的方式來講解不同位置的PRIROR所帶來的不同意義。

          【1】第一個查詢:connect by prior id = manager_id,意思是從當前根記錄開始,查找所有符合條件的記錄:他們的manager_id必須等于當前記錄的id。也就是說查找所有manager_id=2的記錄及其子記錄,很明顯manager_id=2的記錄只有tom和paul,但是由于ben的直接領導tom是mark的下屬,所以ben也是mark的下屬,只不過是間接關系而已。

          【2】第二個查詢:connect by id = prior manager_id,意思是從當前根記錄開始,查找所有符合條件的記錄:他們的id必須等于當前記錄的manager_id。也就是說查找所以id=1的記錄,那么很明顯id=1的記錄只有king。

          總結:Prior放在那里,那一側就是被比較的一方(父方),另一側就是發起比較的一方(子方)。語義上可以這樣翻譯:xxx字段的值必須等于當前記錄XXX字段的值(prior一方)

          參考資料:《Mastering Oracle SQL》(By Alan Beaulieu, Sanjay Mishra O'Reilly June 2004  0-596-00632-2) 


          -------------------------------------------------------------
          生活就像打牌,不是要抓一手好牌,而是要盡力打好一手爛牌。
          posted on 2008-06-11 17:55 Paul Lin 閱讀(4349) 評論(6)  編輯  收藏 所屬分類: Oracle 開發


          FeedBack:
          # re: Oracle開發專題之:級聯查詢(Hierarchical Queries)
          2008-06-15 14:43 | 藍劍
          明白了,謝謝!  回復  更多評論
            
          # re: 【原】Oracle開發專題之:級聯查詢(Hierarchical Queries)
          2008-08-05 21:52 | ppp
          非常謝謝!很好!  回復  更多評論
            
          # re: 【原】Oracle開發專題之:級聯查詢(Hierarchical Queries)
          2008-08-29 18:30 | xwu
          看起來很清晰,很好,謝謝。  回復  更多評論
            
          # re: 【原】Oracle開發專題之:級聯查詢(Hierarchical Queries)
          2009-03-16 10:27 | 取經
          非常好  回復  更多評論
            
          # re: 【原】Oracle開發專題之:級聯查詢(Hierarchical Queries)
          2009-05-17 17:12 | sharepub
          pengpenglin你好,看了寫的原創技術文章,發現你的技術和文字功底還不錯,不知道是否有時間來寫ORACLE 11G開發相關的教程呢?我們是人民郵電出版社和電子工業出版社在成都的編輯中心,易為科技,最近我們剛好有相關教程的出版計劃,如果有意向歡迎進一步聯系:
          msn: sharepub@hotmail.com
          qq: 568001705
          email: wondering2004@sina.com   回復  更多評論
            
          # re: 【原】Oracle開發專題之:級聯查詢(Hierarchical Queries)
          2011-11-04 15:21 | dgds
          樓主好人啊  回復  更多評論
            
          <2008年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          常用鏈接

          留言簿(21)

          隨筆分類

          隨筆檔案

          BlogJava熱點博客

          好友博客

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 朝阳县| 兰溪市| 泗水县| 黄平县| 和田县| 兴山县| 镶黄旗| 连平县| 禄劝| 娱乐| 广水市| 波密县| 温宿县| 浦东新区| 恩施市| 濮阳县| 威信县| 凤庆县| 屏东县| 潞城市| 桦甸市| 天气| 屯留县| 高台县| 祁阳县| 肥城市| 涿鹿县| 错那县| 高密市| 平凉市| 平原县| 白朗县| 宿迁市| 赤壁市| 澎湖县| 阿城市| 平邑县| 五家渠市| 汪清县| 南安市| 紫金县|