將同群組多行字串合併為單一字串,例:
COUNTRY | CITY
中國 | 台北
中國 | 香港
中國 | 上海
日本 | 東京
日本 | 大阪
-- 期望結果
中國 | 台北,香港,上海
日本 | 東京,大阪
| 方案 | 版本 | 語法範例 | 優點 | 缺點/限制 | 排序支援 |
|---|---|---|---|---|---|
| WM_CONCAT | 10g-12c (非文檔化) | WM_CONCAT(city) | 簡單、舊版相容 | 非官方支援、19c 移除、無排序、長度 4000 字元限制 | 無 |
| LISTAGG | 11gR2+ | LISTAGG(city, ',') WITHIN GROUP (ORDER BY city) | 官方標準、支援排序、OVER 分析函數 | 結果長度限制 4000 (VARCHAR2) / 32767 (CLOB 12c+),溢位報 ORA-01489 | 完整 |
| XMLAGG + XMLELEMENT | 9i+ | RTRIM(XMLAGG(XMLELEMENT(E, city, ',').EXTRACT('//text()')), ',') | 無長度限制 (CLOB)、舊版相容 | 語法複雜、效能較差、XML 特殊字元需轉義 | 可控 |
| COLLECT + 自定義型別 | 10g+ | CAST(COLLECT(city) AS SYS.ODCIVARCHAR2LIST) → PL/SQL 迴圈拼接 | 型別安全、可處理複雜邏輯 | 需 PL/SQL 封裝、效能一般 | 可控 |
| 自定義彙總函數 (ODCIAggregate) | 9i+ | CREATE FUNCTION stragg ... IMPLEMENT ODCIAggregate | 語法最簡潔 STRAGG(city)、可封裝邏輯 | 開發成本高、需編譯部署、跨版本相容性測試 | 可控 |
IF 12c+ AND 結果長度 < 32K → LISTAGG (首選)
IF 11gR2-12c AND 結果長度 < 4K → LISTAGG
IF 需無限長度 / 9i-10g → XMLAGG
IF 需複雜邏輯/型別安全 → COLLECT + PL/SQL
IF 追求極致簡潔且願投資開發 → 自定義彙總函數
IF 維護舊系統 10g-11g 且長度 < 4K → WM_CONCAT (謹慎,知曉風險)
-- 12c+ 支援 ON OVERFLOW TRUNCATE
LISTAGG(city, ',' ON OVERFLOW TRUNCATE '...' WITH COUNT) WITHIN GROUP (ORDER BY city)
-- 返回: '台北,香港,上海,...(3 more)' 避免 ORA-01489
-- LISTAGG 標準寫法
SELECT deptno,
LISTAGG(ename, ',') WITHIN GROUP (ORDER BY ename) AS employees
FROM emp
GROUP BY deptno;
-- XMLAGG 兼容寫法
SELECT deptno,
RTRIM(XMLAGG(XMLELEMENT(E, ename, ',') ORDER BY ename).EXTRACT('//text()'), ',') AS employees
FROM emp
GROUP BY deptno;
現代 Oracle (12c+) 首選 LISTAGG,配合 ON OVERFLOW TRUNCATE 解決長度限制。舊版環境用 XMLAGG 保證相容。嚴禁在生產新代碼使用 WM_CONCAT。選型原則:標準優先、相容次之、長度無限制用 XMLAGG、複雜邏輯用 COLLECT/自定義函數。