樹狀結構 (組織架構、選單目錄、BOM 物料清單) 在資料庫中通常以「遞歸外鍵」 (父子欄位自關聯) 方式儲存。Oracle 原生的 START WITH ... CONNECT BY PRIOR 提供宣告式遞歸查詢能力,無需撰寫複雜的 PL/SQL 迴圈或 CTE。本文系統講解語法結構、根節點定義、連接方向控制、層級偽欄位應用,並以部門表為例示範自頂向下與自底向上兩種遍歷模式。
SELECT *
FROM tablename
START WITH cond1 -- 根節點條件
CONNECT BY cond2 -- 父子連接條件 (含 PRIOR)
WHERE cond3; -- 結果過濾條件 (選用)
deptid=76) 或多根節點 (paredeptid=0 代表所有頂層部門)。PRIOR 修飾「父代」欄位。
CONNECT BY PRIOR parent_id = child_id:自頂向下 (父→子)CONNECT BY PRIOR child_id = parent_id:自底向上 (子→父)DEPTID NUMBER -- 部門 ID
PAREDEPTID NUMBER -- 父部門 ID (0 表頂層)
NAME CHAR(40) -- 部門名稱
從部門 76 向上找到根:
SELECT *
FROM persons.dept
START WITH deptid = 76
CONNECT BY PRIOR paredeptid = deptid;
PRIOR paredeptid 代表「上一筆記錄的父部門 ID」等於「本筆記錄的部門 ID」,即向上一層層尋找父節點。
從所有頂層部門 (父部門=0) 向下遞歸:
SELECT *
FROM persons.dept
START WITH paredeptid = 0
CONNECT BY PRIOR deptid = paredeptid;
此處 PRIOR deptid (上一層的 ID) = paredeptid (本層的父 ID),形成父→子遞歸。
使用 LEVEL 偽欄位 (根節點 LEVEL=1):
SELECT a.*, LEVEL
FROM persons.dept a
START WITH paredeptid = 0
CONNECT BY PRIOR deptid = paredeptid;
ORDER SIBLINGS BY 維持同層節點排序,不破壞階層結構。SYS_CONNECT_BY_PATH(name, ' > ') 可產生完整路徑字串 (如「總公司 > 研發部 > 後端組」)。CONNECT BY NOCYCLE PRIOR ... 避免資料臟污導致無限遞歸,並可用 CONNECT_BY_ISCYCLE 標記循環節點。WITH RECURSIVE (11gR2+) 並配合 SEARCH DEPTH FIRST 優化。WHERE 過濾不影響遞歸路徑;若需在遞歸過程中剪枝,需放入 CONNECT BY 條件中 (如 CONNECT BY PRIOR deptid = paredeptid AND status='ACTIVE')。| 需求 | START WITH | CONNECT BY PRIOR |
|---|---|---|
| 從根向下遍歷全樹 | parent_id = 0 (或根節點 ID) | PRIOR child_id = parent_id |
| 從葉向上找祖先鏈 | child_id = :leaf_id | PRIOR parent_id = child_id |
| 多根森林 | parent_id IN (0, -1) | 同單根 |
善用 CONNECT BY 的宣告式特性,能以極簡潔的 SQL 解決複雜的階層查詢問題,是 Oracle 開發者的利器。