oracle 19c未大量新增json功能,核心能力如json_table、json_value等早在12.1/12.2已实现;其重点是提升稳定性、易用性及pl/sql中调用的安全性,增强listagg(distinct)和any_value等辅助函数,并稳定nested路径语法以可靠展开嵌套json数组。
oracle 19c 不是“大量新增 json 功能”的版本——json 核心能力(json_table、json_value、json_object 等)早在 12.1/12.2 就已落地。19c 的重点是让这些能力更稳、更易用、更少出错,尤其在 pl/sql 中调用时不再轻易掉坑。
PL/SQL 中不能直接调用 JSON 函数,必须走 SQL 引擎
这是最常被忽略的前提。你写不出 l_val := json_value(l_json, '$.x') 这样的表达式——JSON_VALUE 是 SQL 函数,不是 PL/SQL 内置过程。PL/SQL 块里所有 JSON 解析动作,本质都是发起一次隐式或显式的 SQL 查询。
- 正确写法:用
SELECT ... INTO把结果查进变量 - 错误写法:把
JSON_OBJECT_T或JSON_ARRAY_T当作纯内存对象,在循环里反复 new + put 而不 clear - 性能影响:每次
SELECT JSON_VALUE(...)都触发一次 SQL 解析和执行,高频调用建议封装为带参数的视图或物化函数 - 兼容性注意:Oracle 12.1–18c 支持基础 JSON 函数但无
JSON_OBJECT_T;该类型直到 23c(PL/SQL 14)才引入,19c 不可用
19c 对 JSON 处理的关键增强:LISTAGG(DISTINCT) 和 ANY_VALUE
这两个不是 JSON 专属函数,但极大简化了从关系数据生成 JSON 所需的预处理逻辑——比如拼接去重标签、避免 GROUP BY 冗余字段。
-
LISTAGG(column, ',') WITHIN GROUP (ORDER BY column) DISTINCT:19c 开始支持DISTINCT关键字,不用再套一层SELECT DISTINCT子查询 -
ANY_VALUE(column):在 GROUP BY 场景下替代MIN/MAX,语义更清晰,且不强制要求字段参与分组,减少 SQL 冗余 - 典型误用:用
LISTAGG拼接 JSON 数组字符串(如'["' || LISTAGG(name, '","') || '"]')——这绕过了类型校验,数字变字符串、null变空串、特殊字符未转义,下游解析必崩
嵌套 JSON 数组展开必须用双层 JSON_TABLE 或 NESTED(12.2+)
面对形如 [{"id":1,"tags":["a","b"]},{"id":2,"tags":["c"]}] 的结构,单层 JSON_TABLE 无法真正“炸开”数组元素。19c 继承并稳定了 12.2 引入的 NESTED 路径语法,这是目前最简洁可靠的解法。
- 错误路径:
PATH '$.tags[0]'—— 只取首项,且索引越界返回 NULL 不报错,静默丢失数据 - 推荐写法(12.2+):
NESTED tags[*] COLUMNS (tag VARCHAR2(10) PATH '$'),自动对每个tags数组做横向展开 - 兼容旧版(12.1):必须嵌套两层
JSON_TABLE,外层取对象,内层传jt1.tags字段再解析数组,代码冗长且易错 - 注意点:
JSON_TABLE必须出现在FROM子句,不能当普通函数调用;路径是相对路径,COLUMNS里的$.name是相对于上一级路径的偏移
别在 19c 里用 PL/JSON 库做基础解析
除非你卡在 11g,否则 PL/JSON 是过时方案。19c 原生 JSON 函数性能更好、类型更安全、错误反馈更明确——而 PL/JSON 依赖字符串拼接构造 JSON,put('age', 25) 实际存的是 "age":"25"(字符串),不是数字,前端反序列化会失败。
- PL/JSON 适用场景:需要动态构建极复杂嵌套结构(如多层条件分支 JSON)、或必须兼容 11g 且无法升级
- 19c 推荐路径:关系数据 → SQL 聚合(
LISTAGG/ANY_VALUE)→JSON_OBJECT/JSON_ARRAY构造 →JSON_TABLE展开验证 - 容易被忽略的细节:
JSON_OBJECT默认跳过NULL字段;若契约要求显式"key": null,必须用JSON_OBJECT(KEY 'key' IS NULL)或升级到 23c 的put_null()
真正麻烦的从来不是语法怎么写,而是搞不清哪一步在 SQL 引擎里跑、哪一步在 PL/SQL 引擎里跑。19c 没有改变这个根本约束,只是让边界更清晰、容错更强一点。











