需求:將單一欄位的多行查詢結果**串聯為單一字串**,行間以分隔符 (如 `;`) 分隔。Oracle 11g+ 推薦使用 LISTAGG,但舊版本可利用階層查詢 SYS_CONNECT_BY_PATH 達成。
SELECT SUBSTR(SYS_CONNECT_BY_PATH(dutywork, ';'), 2) AS all_duties
FROM (SELECT dutywork, ROWNUM rn FROM t_test)
WHERE CONNECT_BY_ISLEAF = 1
START WITH rn = 1
CONNECT BY PRIOR rn = rn - 1;
ROWNUM 作為層級序號 (1,2,3...)。START WITH rn=1 從第一行開始。CONNECT BY PRIOR rn = rn-1 串聯成鏈:1→2→3...。SYS_CONNECT_BY_PATH(col, ';') 遞迴拼接路徑:;val1;val2;val3。CONNECT_BY_ISLEAF=1 只取葉節點 (最後一行) 得到完整路徑。SUBSTR(..., 2) 移除前導分隔符。-- 標準 SQL,效能更好、語法更清晰
SELECT LISTAGG(dutywork, ';') WITHIN GROUP (ORDER BY rn) AS all_duties
FROM (SELECT dutywork, ROWNUM rn FROM t_test);
| 方法 | 版本 | 效能 | 適用場景 |
|---|---|---|---|
| LISTAGG | 11gR2+ | 高 | 標準首選,支援 OVERFLOW 截斷處理 (19c+) |
| WM_CONCAT | 10g-12c | 中 | 非文檔化內建,12c 後棄用 |
| XMLAGG + XMLELEMENT | 9i+ | 中 | 舊版本通用,需處理 XML 實體轉義 |
| SYS_CONNECT_BY_PATH | 9i+ | 低 | 階層查詢 Hack,大資料量效能差 |
| PL/SQL 迴圈拼接 | 所有 | 低 | 極複雜邏輯/需程式控制 |
SYS_CONNECT_BY_PATH 屬於**串列遞迴**,資料量超過數千行會明顯變慢,建議改用 LISTAGG 或自訂聚合函數。LISTAGG(...) ON OVERFLOW TRUNCATE '...' WITH COUNT 可防止 4000 位元組限制報錯。