<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 262,  comments - 221,  trackbacks - 0
    目錄:
    =========================================
    1.使用偽列Level顯示表中節點的層次關系
    2.統計表中節點的層數
    3.統計表中各個層次的節點數量
    4.查找表中各個層次的節點信息
    5.在Start with中使用子查詢
    6.判斷節點和節點之間是否具有層次關系
    7.刪除級聯表中的子樹

    一、使用偽列Level顯示表中節點的層次關系:

    Oracle9i對級聯查詢的支持不僅在于提供了像Start with...Connect by這樣的子句供我們很方便地執行查詢,而且還提供了一個偽列(Pseudocolumn): Level。這個偽列的作用是在遞歸查詢的結果中用來表示節點在整個結構中所處的層次。下面我們來看看實際的例子:

    還是上次那個employee表,現在我們要在上次的需求上面增加點小玩意:輸出每個節點的層次值,看如下SQL:
    SQL> select level, id, emp_name, manager_id from employee start with id = 2 connect by prior id = ma
    nager_id 
    order by id;

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

    SQL
    > 

    我們可以看到在LEVEL列,輸出了1,2,2,3的值,這就是Oracle為我們提供的一個偽列。此偽列只能用在start with...connect by子句中,下面我們來看另一種方式是否可行:
    SQL> select level, p.* from (select * from employee start with id = 2 connect by prior id = manager_
    id 
    order by id) p;

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

    SQL
    > 

    可以看到Level列的值全部變成了0,可見在這里Oracle并不認為虛表P里面的數據是“層次關系”,因而對于Level都返回0

    二、統計表中節點的層數:

    假設現在我們想看一下當前employee表中員工總共分為幾個級別,我們應該如何做呢?請看下面的SQL
    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.

    SQL
    > 
    SQL
    > 
    SQL
    > select count(levelfrom employee start with manager_id is null connect by prior id = manager_i
    d;

    COUNT(LEVEL)
    ------------
               7

    SQL
    > 
    SQL
    > select count(distinct levelfrom employee start with manager_id is null connect by prior id = 
    manager_id;

    COUNT(DISTINCTLEVEL)
    --------------------
               4

    從這里我們可以看到,在統計的時候一定要使用distinct關鍵字,否則得到的錯誤的結果。

    三、統計表中各個層次的節點數量:

    假設我們想知道employee表中每個級別的員工數量,我們應該如何做呢--對了,使用Level和group by子句了
    SQL> select levelcount(levelfrom employee start with manager_id is null connect by prior id = ma
    nager_id 
    group by level;

         
    LEVEL COUNT(LEVEL)
    ---------- ------------
             1            1
             
    2            2
             
    3            3
             
    4            1

    四、查找表中各個層次的節點信息:

    上面的例子很簡單,我們看到Level可以用在group by子句中,現在我們更進一步,查看指定層次的員工信息,比如說我現在打算查看Level=2的所有員工的記錄,應該如何做呢?很自然地我們想到了第一個SQL語句:
    SQL> select level, id, emp_name, manager_id from employee where level >= 2;

    no rows selected

    很奇怪吧,這這里level關鍵字就不起作用了,這是因為level偽列只能在和start with...connect by子句結合時才能發揮作用,就想上面的統計各層節點數量一樣,于是我們又立馬想到了第二個SQL語句:
    select *
      
    from (select level, id, emp_name, manager_id
              
    from employee
             start 
    with manager_id is null
            connect 
    by prior id = manager_id
             
    order by id) p
     
    where p.level = 2

    看起來這個句子沒有什么問題吧,實際執行的效果如何呢?我們在SQL*PLUS下執行,結果卻是報錯:
    ERROR at line 1:
    ORA
    -01747: invalid user.table.columntable.columnor column specification

    很郁悶!為什么會報p.level不可識別呢?這是因為level是Oracle的偽列,并不屬于任何一個表,我們必須使用別名把這個偽列“偽裝”成一個實際的列,現在我們看第三個語句,注意語句高亮處。
    SQL> select *
      
    2    from (select level emp_level , id, emp_name, manager_id
      
    3            from employee
      
    4           start with manager_id is null
      
    5          connect by prior id = manager_id
      
    6           order by id) p
      
    7   where p.emp_level = 2;

     EMP_LEVEL         ID EMP_NAME             MANAGER_ID
    ---------- ---------- -------------------- ----------
             2          2 mark                          1
             
    2          3 bob                           1

    SQL
    > 

    這次終于搞定了!不過實際上我們有更簡單的解決方法,請看第四個SQL語句:
    SQL> select level, id, emp_name, manager_id
      
    2    from employee
      
    3   where level = 2
      
    4   start with manager_id is null
      
    5  connect by prior id = manager_id
      
    6   order by id;

         
    LEVEL         ID EMP_NAME             MANAGER_ID
    ---------- ---------- -------------------- ----------
             2          2 mark                          1
             
    2          3 bob                           1

    上面我們是查看某個層次的所有節點信息,現在我們打算看看所有層次的節點信息,而且要求用一種直觀的信息顯示出來。下面的例子演示了如何使用空格縮進的方式來直觀顯示節點之間的層次關系:
    SQL> select level, id, lpad('  '2 * (level - 1)) || emp_name name, manager_id
      
    2    from employee
      
    3   start with manager_id is null
      
    4  connect by prior id = manager_id;

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

    7 rows selected.

    請注意這里的lpad函數的作用,正是它利用了層次和空格進行縮進,讓我們可以很直觀地從NAME字段對齊方式就知道各個節點的層次關系。如果我們需要過濾其中的某些節點,只需要將where條件加在start with前面就可以了(注意必須是前面,否則會報語法錯誤)。

    五、在Start with中使用子查詢:

    在前面我們看到的例子中,start with的值都是一個固定的內容,但有些時候查詢的起始點并不容易確定,比如:查詢工號最小的員工節點及其子節點,這個時候工號最小很明顯是一個查詢的條件,需要我們先通過執行一個查詢得到確定的值,再作為查詢的起點。請看例子:
    SQL> select level, id, lpad('  '2 * (level - 1)) || emp_name name, manager_id
      
    2    from employee
      
    3   start with id = (select min(id) from employee)
      
    4  connect by prior id = manager_id;

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

    7 rows selected.

    六、判斷節點和節點之間是否具有層次關系:

    在日常工作中除了查詢節點的信息之外,另一個常見的應用就是判斷某個節點和另外一個/些節點之間是否具有層次關系。例如我想知道員工mark是不是員工jack的領導(直接或間接的都可以),我應該怎么做呢?

    考慮到start with...connect by會返回一棵節點樹,假如節點數上沒有jack節點,那么說明mark并不是jack的直接或間接領導,如果找到那說明mark是jack的父節點。方法簡單
    SQL> select level,
      
    2         id,
      
    3         lpad('  '2 * (level - 1)) || emp_name employee_name,
      
    4         manager_id
      
    5    from employee
      
    6   where emp_name = 'jack'
      
    7   start with emp_name = 'mark'
      
    8  connect by prior id = manager_id;

    no rows selected

    七、刪除級聯表中的子樹:

    假設現在employee表中的mark及其下屬員工離職,那么我們為了維護數據的完整性,必須將mark及其下屬員工的節點都刪除,有了start with...connect by和level我們就可以輕松地做到這一點了。

    【1】按名稱刪除節點樹:
    SQL> delete from employee
      
    2   where id in (select id
      
    3                  from employee
      
    4                 start with emp_name = 'mark'
      
    5                connect by prior id = manager_id);

    4 rows deleted.

    【2】按層次刪除節點樹:

    從上面的例子我們知道只需要在第一個SQL的基礎上改變一下:使用level區分節點的層次就做到了。

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


    -------------------------------------------------------------
    生活就像打牌,不是要抓一手好牌,而是要盡力打好一手爛牌。
    posted on 2008-06-12 17:45 Paul Lin 閱讀(3957) 評論(0)  編輯  收藏 所屬分類: Oracle 開發
    <2008年6月>
    25262728293031
    1234567
    891011121314
    15161718192021
    22232425262728
    293012345

    常用鏈接

    留言簿(21)

    隨筆分類

    隨筆檔案

    BlogJava熱點博客

    好友博客

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 成人在线免费视频| 无码人妻久久一区二区三区免费丨 | caoporm碰最新免费公开视频| 亚洲综合在线另类色区奇米| 91免费国产在线观看| 苍井空亚洲精品AA片在线播放 | 一级做a爰片久久毛片免费看| 久久久久亚洲精品影视| 国内自产拍自a免费毛片| 国产在线观看免费av站| 成人性生交大片免费看中文| 亚洲精品国产专区91在线| 亚洲av无码成人精品区| 国产大片免费网站不卡美女 | 中文字幕一区二区免费| 亚洲а∨天堂久久精品9966| 中文字幕一精品亚洲无线一区| 三年片在线观看免费大全| a级在线免费观看| 国产亚洲欧美在线观看| 亚洲人成人77777在线播放| 亚洲一区二区三区自拍公司| 偷自拍亚洲视频在线观看99| 亚洲一卡2卡三卡4卡有限公司| 7x7x7x免费在线观看| 日韩久久无码免费毛片软件| 亚洲国产日韩精品| 久久久亚洲AV波多野结衣| 亚洲日本乱码在线观看| 免费h黄肉动漫在线观看| 最近中文字幕免费mv视频7 | 亚洲成色在线综合网站| 国产精品高清全国免费观看| 波多野结衣中文字幕免费视频 | 色窝窝亚洲av网| 99久久国产亚洲综合精品| 自怕偷自怕亚洲精品| 亚洲AV电影院在线观看| 国产av无码专区亚洲av果冻传媒| 国产午夜免费秋霞影院| 一级做a爰片性色毛片免费网站 |