首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

Oracle CONNECT BY PRIOR 遞歸查詢:從葉子節點反向尋找根節點

     編輯:Oracle 資料庫相關知識

場景

表 `TRANS_INST` 存儲樹狀結構:

  • `TRANS_ID`:子節點 ID
  • `UP_TRANS_ID`:父節點 ID

需求:給定任一節點 (如 `480242`),找出該節點為根的子樹中所有葉子節點。

核心 SQL

SELECT trans_id
FROM trans_inst
WHERE CONNECT_BY_ISLEAF = 1
START WITH trans_id = 480242
CONNECT BY PRIOR up_trans_id = trans_id;

關鍵字解析

子句作用
START WITH trans_id = 480242指定遞歸起點 (根節點)
CONNECT BY PRIOR up_trans_id = trans_id定義父子關係:當前行的 `up_trans_id` = 父行的 `trans_id` (反向遍歷)
CONNECT_BY_ISLEAF偽欄位:1=葉子節點 (無子節點),0=非葉子
WHERE CONNECT_BY_ISLEAF = 1過濾僅保留葉子節點

正向 vs 反向遍歷對照

方向START WITHCONNECT BY PRIOR用途
自頂向下 (根→葉)根節點 ID`PRIOR trans_id = up_trans_id`展開子樹、層級報表
自底向上 (葉→根)葉/任意節點 ID`PRIOR up_trans_id = trans_id`尋找祖先鏈、根因分析

實用擴展

1. 顯示完整路徑 (SYS_CONNECT_BY_PATH)

SELECT trans_id,
       SYS_CONNECT_BY_PATH(trans_id, ' → ') AS path_from_root
FROM trans_inst
WHERE CONNECT_BY_ISLEAF = 1
START WITH trans_id = 480242
CONNECT BY PRIOR up_trans_id = trans_id;

2. 限制遞歸深度

SELECT trans_id
FROM trans_inst
WHERE CONNECT_BY_ISLEAF = 1
  AND LEVEL <= 5  -- 最多 5 層
START WITH trans_id = 480242
CONNECT BY PRIOR up_trans_id = trans_id;

3. 循環檢測 (NOCYCLE)

SELECT trans_id
FROM trans_inst
WHERE CONNECT_BY_ISLEAF = 1
START WITH trans_id = 480242
CONNECT BY NOCYCLE PRIOR up_trans_id = trans_id;
-- 若資料有環,NOCYCLE 避免無限循環,並可用 CONNECT_BY_ISCYCLE 檢測

4. 12c+ 標準遞歸 CTE 寫法 (更符合 ANSI SQL)

WITH RECURSIVE tree AS (
  SELECT trans_id, up_trans_id, 1 AS lvl
  FROM trans_inst
  WHERE trans_id = 480242
  UNION ALL
  SELECT t.trans_id, t.up_trans_id, tree.lvl + 1
  FROM trans_inst t
  JOIN tree ON t.up_trans_id = tree.trans_id
  WHERE tree.lvl < 100  -- 防無限遞歸
)
SELECT trans_id FROM tree
WHERE trans_id NOT IN (SELECT up_trans_id FROM trans_inst);  -- 葉子節點

效能提示

  • 在 `TRANS_ID`、`UP_TRANS_ID` 建立索引。
  • 大樹結構考慮物化路徑 或嵌套集合 模型替代遞歸查詢。
  • 避免在高併發核心鏈路使用 `CONNECT BY`,改用應用層快取或預計算。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved