Oracle 12c+推荐用JSON_TABLE高效转关系表,须在FROM中配合横向连接使用;路径为相对路径,嵌套数组需NESTED或双层调用;PL/SQL中须通过SELECT调用JSON函数,性能依赖IS JSON约束与虚拟列索引。
oracle 12c 及以上版本原生支持 json,json_table 是最高效、最标准的“json 转关系表”方式;pl/sql 中直接解析 json 应优先用内置函数,而非 pl/json 库——除非你卡在 11g 或必须做复杂动态构建。
JSON_TABLE 的基本调用结构必须写对
错把 JSON_TABLE 当成普通函数调用,是新手最常踩的坑。它只能出现在 FROM 子句里,且必须配合横向连接(implicit lateral join)使用:
-
JSON_TABLE第一个参数是表达式(如列名json_col、绑定变量:json_str或字面量'{"a":1}'),不是字符串拼接结果 - 第二个参数是路径表达式,
'$'表示根对象,'$[*]'表示数组所有元素,'$.items[*]'表示嵌套数组 -
COLUMNS子句里的每个PATH是相对于上一级路径的相对路径,不是从根开始重写 —— 比如JSON_TABLE(..., '$.data' COLUMNS (name PATH '$.name'))中的'$.name'实际查的是$.data.name - 别漏写
FORMAT JSON:当某列要返回原始 JSON 片段(比如子对象或数组)时,必须显式声明FORMAT JSON,否则 Oracle 会尝试转成字符串并截断
处理嵌套数组时,路径和层级容易错乱
遇到 [{"id":1,"tags":["a","b"]},{"id":2,"tags":["c"]}] 这类结构,想展开成每行一个 tag,不能只用一层 JSON_TABLE。必须嵌套调用,或用 NESTED 路径:
- 错误写法:
JSON_TABLE(json_col, '$[*]' COLUMNS (id NUMBER PATH '$.id', tag VARCHAR2(10) PATH '$.tags[0]'))—— 只取了第一个 tag,且无法展开全部 - 正确做法一(双层
JSON_TABLE):SELECT jt1.id, jt2.tag FROM json_table(...) jt1, JSON_TABLE(jt1.tags, '$[*]' COLUMNS (tag VARCHAR2(10) PATH '$')) jt2 - 正确做法二(
NESTED路径,12.2+):JSON_TABLE(json_col, '$[*]' COLUMNS (id NUMBER PATH '$.id', NESTED tags[*] COLUMNS (tag VARCHAR2(10) PATH '$'))) - 注意:数组索引越界默认返回 NULL,不报错;若需严格控制,加
ERROR ON ERROR子句
PL/SQL 块里调用 JSON_TABLE 要走 SQL 引擎,不能直接“解析”
PL/SQL 本身不提供 JSON 解析器对象(如 JavaScript 的 JSON.parse())。所谓“PL/SQL 处理 JSON”,本质是通过 SQL 函数在 SQL 引擎中执行,再把结果 SELECT 进 PL/SQL 变量:
- 不能写
DECLARE l_json CLOB := '{"x":1}'; l_val := json_value(l_json, '$.x');——JSON_VALUE是 SQL 函数,不能在纯 PL/SQL 表达式中直接调用 - 必须写成
SELECT JSON_VALUE(l_json, '$.x') INTO l_val FROM DUAL; - 批量处理建议用游标:
FOR r IN (SELECT * FROM JSON_TABLE(...)) LOOP ... END LOOP;,避免在循环里反复解析同一 JSON 字符串 - 如果 JSON 结构极不固定、字段名动态变化,才考虑引入 PL/JSON 库,但要注意它不支持
JSON_TABLE那样的 SQL 优化路径,性能差一个数量级
性能与兼容性关键点
JSON_TABLE 的性能高度依赖底层 JSON 数据是否已建索引或标记为 IS JSON 约束:
- 没加
CHECK (col IS JSON)的列,每次调用JSON_TABLE都会全量校验 JSON 格式,开销大 - 对高频查询的路径(如
$.order_id),可建虚拟列 + 函数索引:ALTER TABLE t ADD (order_id AS JSON_VALUE(json_col, '$.order_id')); CREATE INDEX idx_order_id ON t(order_id); - Oracle 12.1 不支持
NESTED和ORDINALITY列;12.2+ 才支持ERROR ON ERROR和更灵活的错误处理 - 金仓 KES(KINGBASE)虽兼容大部分 PL/SQL 语法,但
JSON_TABLE行为与 Oracle 有细微差异,尤其是路径错误时的默认返回值,上线前务必实测
真正难的不是写对第一行 JSON_TABLE,而是搞清 JSON 数据的“真实形状”——空数组、缺失字段、null 值、数字被存成字符串……这些都会让路径匹配静默失败。建议先用 JSON_EXISTS 做探针,再用 JSON_TABLE 展开。


















