CREATE TABLE test_tree (
id NUMBER PRIMARY KEY,
pid NUMBER, -- 父節點 ID,根節點 PID=0 或 NULL
name VARCHAR2(50)
);
INSERT INTO test_tree VALUES (1, 0, 'Root');
INSERT INTO test_tree VALUES (2, 0, 'Root2');
INSERT INTO test_tree VALUES (3, 1, 'Child1-1');
INSERT INTO test_tree VALUES (4, 1, 'Child1-2');
INSERT INTO test_tree VALUES (5, 2, 'Child2-1');
INSERT INTO test_tree VALUES (6, 2, 'Child2-2');
INSERT INTO test_tree VALUES (7, 3, 'Leaf1-1-1');
INSERT INTO test_tree VALUES (8, 4, 'Leaf1-2-1');
INSERT INTO test_tree VALUES (9, 5, 'Leaf2-1-1');
SELECT *
FROM test_tree
START WITH id = 1 -- 根節點條件
CONNECT BY PRIOR id = pid -- 遞歸關係:父 ID = 子 PID
ORDER BY id; -- 同層排序
| 偽欄位/函數 | 含義 | 示例 |
|---|---|---|
| LEVEL | 層級深度 (根=1) | `LEVEL` |
| SYS_CONNECT_BY_PATH(col, '/') | 從根到當前節點路徑 | `/Root/Child1-1/Leaf1-1-1` |
| CONNECT_BY_ISLEAF | 是否葉子節點 (1=是) | 篩選葉子 |
| CONNECT_BY_ROOT col | 根節點的該欄位值 | 歸屬頂層部門 |
| NOCYCLE | 檢測循環引用 (10g+) | `CONNECT BY NOCYCLE PRIOR id = pid` |
| CONNECT_BY_ISCYCLE | 是否為循環節點 | 配合 NOCYCLE 使用 |
-- 只查詢名稱包含 'Child' 的分支,但保留其完整祖先路徑
SELECT *
FROM test_tree
WHERE name LIKE '%Child%' -- 過濾在 START WITH 之前執行 (10g+)
START WITH id = 1
CONNECT BY PRIOR id = pid;
-- 若需在遞歸過程中過濾 (如只遞歸啟用狀態的節點)
SELECT *
FROM test_tree
START WITH id = 1
CONNECT BY PRIOR id = pid
AND status = 'ACTIVE'; -- 遞歸條件加入狀態判斷
WITH RECURSIVE tree_path (id, pid, name, lvl, path) AS (
-- Anchor member
SELECT id, pid, name, 1, '/'||name
FROM test_tree
WHERE id = 1
UNION ALL
-- Recursive member
SELECT t.id, t.pid, t.name, tp.lvl+1, tp.path||'/'||t.name
FROM test_tree t
JOIN tree_path tp ON t.pid = tp.id
WHERE tp.lvl < 10 -- 防無限遞歸深度限制
)
SELECT * FROM tree_path ORDER BY lvl, id;
`START WITH ... CONNECT BY` 是 Oracle 獨有的階層查詢語法,簡潔強大;**`WITH RECURSIVE` CTE 是 ANSI SQL 標準、功能更豐、可移植**,為現代應用首選。掌握兩種寫法、偽欄位應用、索引優化與循環檢測,即可輕鬆構建任意深度的樹狀資料應用。