ORA-01489错误源于LISTAGG返回VARCHAR2硬限4000字节,含中文时更易触发;推荐用XMLAGG+XMLPARSE组合返回CLOB,兼容10g+、支持排序去重、避免截断丢数据。

LISTAGG 报 ORA-01489 错误时别硬扛
直接换方案。LISTAGG 返回 VARCHAR2,硬上限 4000 字节,超出就抛 ORA-01489: result of string concatenation is too long。强行用 DBMS_LOB.SUBSTR 截断会丢数据,且无法解决根本问题。
常见错误场景:
- 拼接字段含中文、长地址、多条备注,合计轻松破 2000 字符
- 分组后每组记录数波动大,测试环境不报错,生产一查就崩
- 加了
WITHIN GROUP (ORDER BY ...)仍报错——排序不缓解长度限制
此时应放弃 LISTAGG,转向能返回 CLOB 的方案。
XMLAGG + XMLPARSE 是当前最稳的替代写法
XMLAGG 本身返回 XMLTYPE,配合 XMLPARSE(CONTENT ... WELLFORMED) 和 .GETCLOBVAL() 可安全产出超长字符串(理论支持 4GB),且 Oracle 10g 起就稳定可用。
标准写法(带排序、去尾逗号):
SELECT deptno,
RTRIM(
XMLAGG(
XMLPARSE(CONTENT ename || ',' WELLFORMED)
ORDER BY ename
).GETCLOBVAL(),
','
) AS emp_list
FROM emp
GROUP BY deptno;
注意点:
-
ename必须是字符类型,否则先套TO_CHAR(ename) -
RTRIM(..., ',')仅处理末尾一个逗号;若原始数据含逗号,它不会误删 -
XMLPARSE中的WELLFORMED是必须关键字,漏写会报ORA-31061 - 性能比
LISTAGG略低,但对万级以内分组行数无感知
WM_CONCAT 已不可靠,除非你控制所有数据库版本
WMSYS.WM_CONCAT 在 Oracle 12c+ 默认禁用,19c 后基本消失。即使手动解锁 WMSYS 并重建函数,也会面临:
- 非官方支持,补丁升级可能直接失效
- 不支持
ORDER BY,拼接顺序不可控 - 无法去重(
WM_CONCAT(DISTINCT ...)语法在多数版本报错) - 返回仍是
VARCHAR2,同样有 4000 字节天花板
如果你维护的是混合版本库(比如同时跑 11g 和 19c),绝不要把它写进核心报表 SQL。
多字段拼接或需去重时,先子查询再聚合
原生 XMLAGG 不支持 DISTINCT,要实现“分组内去重后拼接”,不能指望函数参数解决,得靠结构控制:
例如:按部门拼接不重复的职位列表
SELECT deptno,
RTRIM(
XMLAGG(
XMLPARSE(CONTENT job || ',' WELLFORMED)
ORDER BY job
).GETCLOBVAL(),
','
) AS job_list
FROM (
SELECT DISTINCT deptno, job FROM emp
) t
GROUP BY deptno;
关键逻辑:
- 去重必须放在
GROUP BY外层的子查询里,不是函数里 - 若需拼接多个字段(如
job || '(' || ename || ')'),也必须在子查询中构造好 - 避免在
XMLAGG内做复杂表达式,易触发隐式类型转换失败
真正容易被忽略的点是:当拼接结果最终要传给 Java 或 Python 应用时,CLOB 类型需显式调用 .toString() 或 .read(),否则可能只取前 4000 字符——这不是 SQL 问题,而是客户端驱动行为。











