JSON_OBJECTAGG是Oracle 21c的聚合函数,非窗口函数,不支持OVER子句;要求键值均为非空字符串,键重复时保留最后值,键超长会静默截断。

Oracle 21c 中 JSON_OBJECTAGG 的基本用法与限制
Oracle 21c 支持 JSON_OBJECTAGG,但它**不是窗口函数**,不接受 OVER 子句;若强行写,会报错 ORA-30498: invalid use of an analytic function。该函数严格要求两个参数:第一个为键(key),第二个为值(value),且任意一个为 NULL 就直接报错,不会跳过。
常见错误现象包括:
- SELECT 中漏写
GROUP BY—— 报ORA-00937: not a single-group group function - 键列含
NULL值 —— 报ORA-40478: maximum number of JSON object members (50000) exceeded或更常见的ORA-40443: invalid key value in JSON_OBJECTAGG - 未显式转换类型,比如用数字列当键 —— Oracle 不自动转字符串,会报
ORA-40467: cannot convert argument to string
实操建议:
- 键列务必用
TO_CHAR()或CAST(... AS VARCHAR2(4000))显式转字符串 - 提前过滤掉键为
NULL的行:WHERE key_col IS NOT NULL AND value_col IS NOT NULL - 若需去重键,靠
GROUP BY+ 子查询控制顺序(因重复键保留最后一条,而默认无序),例如加ROW_NUMBER() OVER (PARTITION BY key_col ORDER BY update_ts DESC)预处理
JSON_ARRAYAGG 在 Oracle 21c 中的空值与重复行为
JSON_ARRAYAGG 默认保留所有非 NULL 值,包括重复项;它**不会自动去重**,也不会报错。但要注意:如果输入全是 NULL,返回的是空数组 [],不是 NULL;如果某行为 ''(空字符串),会被转成 "\u0000" —— 这在前端解析时可能出问题。
性能与兼容性影响:
- 大数据量下(如百万行聚合),
JSON_ARRAYAGG比LISTAGG内存开销更大,容易触发ORA-04030: out of process memory - Oracle 21c 开始支持
DISTINCT修饰符:JSON_ARRAYAGG(DISTINCT col),但不支持DISTINCT BY(...)(那是 IRIS 的语法,Oracle 不认) - 若字段含双引号或反斜杠,
JSON_ARRAYAGG会自动转义,无需手动处理 —— 但这也意味着你不能靠字符串拼接绕过转义逻辑
示例(安全写法):
SELECT deptno,
JSON_ARRAYAGG(
JSON_OBJECT('empno' VALUE empno, 'ename' VALUE ename)
FORMAT JSON
) AS emp_list
FROM emp
WHERE ename IS NOT NULL
GROUP BY deptno;
组合使用 JSON_OBJECTAGG 和 JSON_ARRAYAGG 构建嵌套结构
Oracle 21c 允许在 JSON_OBJECTAGG 的 value 表达式里嵌套 JSON_ARRAYAGG,这是构建「对象内含数组」结构的唯一标准方式。但必须注意执行顺序:先分组聚合数组,再用外层聚合组装对象 —— 不能反过来。
容易踩的坑:
- 在同一个
SELECT中对同一张表既用JSON_OBJECTAGG又用JSON_ARRAYAGG,但没统一GROUP BY维度,会导致结果行数不匹配或报错 - 误以为
JSON_OBJECTAGG(key, JSON_ARRAYAGG(...))能自动按 key 分组数组 —— 实际上JSON_ARRAYAGG作用域是整个GROUP BY分组,不是按 key 动态切片 - 忘记加
FORMAT JSON—— 若子查询返回的是字符串而非 JSON 类型,外层JSON_OBJECTAGG会把它当普通字符串包裹,导致双引号被转义成\"...
正确结构依赖子查询或 CTE 分层处理,例如:
WITH dept_emps AS (
SELECT deptno, JSON_ARRAYAGG(
JSON_OBJECT('empno' VALUE empno, 'job' VALUE job)
) AS emps_json
FROM emp GROUP BY deptno
)
SELECT JSON_OBJECTAGG(
TO_CHAR(deptno) VALUE emps_json
) AS dept_tree
FROM dept_emps;
Oracle 21c JSON 聚合函数对 CLOB 和字符长度的隐式约束
JSON_OBJECTAGG 和 JSON_ARRAYAGG 的返回类型是 CLOB,但它们内部仍受 Oracle 字符长度语义影响。如果键或值表达式结果超过 32767 字节(在 AL32UTF8 字符集下,一个中文常占 3 字节),可能截断或报 ORA-40470: JSON generation error。
关键点:
- 不支持
ON OVERFLOW TRUNCATE这类 MySQL/PostgreSQL 风格的容错选项 —— Oracle 21c 没有该语法 - 若值列是
CLOB类型,必须显式用DBMS_LOB.SUBSTR(clob_col, 32767, 1)截断,否则聚合时报错 -
JSON_OBJECTAGG键名长度上限为 4000 字符;超长键会被静默截断,但不会报错 —— 这极易引发键冲突却难以察觉
真正麻烦的地方在于:这些长度限制不报明确错误,而是表现为结果缺失、JSON 解析失败或前端显示乱码。调试时得逐层检查中间结果的 DBMS_LOB.GETLENGTH,而不是只看最终输出。


















