Oracle CONNECT BY PRIOR 是處理樹狀/層級結構資料(組織架構、物料清單、目錄分類)的標準 SQL 擴展。本文系統講解語法結構、遍歷邏輯、PRIOR 位置決定的遍歷方向、LEVEL 偽欄應用、節點/分支剪枝、排序顯示及效能優化技巧。
SELECT column_list
FROM table_name
[WHERE condition3] -- 過濾條件,作用於最終結果集
[START WITH condition1] -- 根節點定義(可選,省略則所有滿足條件行為根)
CONNECT BY condition2; -- 遞歸連接條件(必須包含 PRIOR)
PRIOR 必須放在連接條件等號兩側之一,表示「父節點」欄位:
CONNECT BY PRIOR parent_id = child_idCONNECT BY PRIOR empno = mgr(empno 為父,mgr 為子)CONNECT BY child_id = PRIOR parent_idCONNECT BY mgr = PRIOR empno⚠️ PRIOR 只能出現一次,且必須在等號直邊,不能用在運算式內部。
START WITH 確定的根節點開始(可多根,形成森林)。此為標準樹的深度優先前序走訪,輸出順序即為遍歷順序。
-- 自頂向下:從 KING(7839) 往下查所有下屬
SELECT empno, ename, mgr, LEVEL
FROM emp
START WITH empno = 7839
CONNECT BY PRIOR empno = mgr;
-- 自底向上:從 MILLER(7934) 往上查所有主管
SELECT empno, ename, mgr, LEVEL
FROM emp
START WITH empno = 7934
CONNECT BY mgr = PRIOR empno;
| 偽欄/函數 | 說明 |
|---|---|
LEVEL | 根節點=1,每層遞增。不受 START WITH 位置影響,根永遠為 1。 |
CONNECT_BY_ISLEAF | 1=葉節點,0=非葉節點。 |
CONNECT_BY_ROOT(col) | 返回當前節點所屬樹的根節點 col 值。 |
SYS_CONNECT_BY_PATH(col, '/') | 返回從根到當前節點的路徑字串(如 /KING/JONES/SCOTT)。 |
NOCYCLE | 11g+ 關鍵字,檢測循環引用避免無限遞歸(需配合 CONNECT_BY_ISCYCLE)。 |
WHERE 子句:過濾最終結果集,不影響遍歷過程。被過濾節點的子孫仍會被遍歷並可能出現在結果中。CONNECT BY 條件中加入過濾:影響遍歷,可實現分支剪枝。CONNECT BY PRIOR empno = mgr AND deptno != 10(跳過 10 號部門整個子樹)。ORDER SIBLINGS BY col:同層節點按 col 排序,保持父子層級關係。ORDER SIBLINGS BY enameORDER BY:打破層級順序,僅按欄位排序最終結果。mgr)與子鍵欄(empno)均建立索引,加速父子關聯查找。START WITH 條件應高選擇性,利用索引快速定位根節點集合。WHERE LEVEL <= 5 限制最大深度,防止失控遞歸。主流 ORM 框架(Hibernate、MyBatis)不直接支援 CONNECT BY。建議方案:
<select> 直接編寫原生 SQL,利用 resultMap 映射遞歸結果集。