oracle 19c中json解析必须由sql引擎执行,pl/sql不支持直接赋值调用json_table或json_value;正确方式是select...into配合json_table(需from子句)或json_value(须from dual),嵌套数组须用nested path且注意null on empty行为。

Oracle 19c 的 JSON 大字段(JSON 类型列或 CLOB)不能在 PL/SQL 中直接用赋值语句解析,所有解析必须交由 SQL 引擎执行;否则会报 PLS-00222 或 ORA-00923 —— 这不是配置问题,是语言层限制。
JSON_TABLE 必须作为派生表出现在 FROM 子句中
你不能写 l_name := JSON_TABLE(...) 或 SELECT JSON_TABLE(...) FROM t。它不是函数,是表构造器,只接受 SQL 上下文。
- 正确姿势:用逗号连接或
LATERAL关联,例如SELECT jt.name FROM t, JSON_TABLE(t.json_col, '$' COLUMNS (name VARCHAR2(50) PATH '$.name')) jt - PL/SQL 块中必须配合
SELECT ... INTO,例如:SELECT jt.name INTO l_name FROM DUAL, JSON_TABLE(:json_str, '$' COLUMNS (name VARCHAR2(50) PATH '$.name')) jt; - 路径参数支持字面量(
'{"a":1}')、绑定变量(:json_str)、列名(t.json_col),但不支持字符串拼接(如'{"a":' || 1 || '}')
嵌套数组必须用 NESTED PATH,别手动写两层 JSON_TABLE
面对 {"orders":[{"id":1,"items":[{"sku":"A"},{"sku":"B"}]}]} 这类结构,硬套两层 JSON_TABLE 容易引入笛卡尔积、空数组丢行、类型不匹配(jt1.items 是 JSON 类型片段,不是字符串)。
- 19c 推荐用
NESTED PATH:路径是相对的,NESTED PATH '$.items[*]'中的$指向上一级对象(每个 order),不是根节点 - 加
NULL ON EMPTY可保留缺失items的订单行,否则整行被过滤 - 错误示例:
sku VARCHAR2(20) PATH '$.items[0].sku'—— 只取第一个 item,且 items 为空时无结果
PL/SQL 中调用 JSON_VALUE 也必须走 SELECT INTO
JSON_VALUE 看似像函数,但在 PL/SQL 表达式里直接调用会报 PLS-00222。它和 JSON_TABLE 一样,属于 SQL 引擎能力,PL/SQL 本身没有 JSON 解析器。
- 单字段:用
SELECT JSON_VALUE(:json_str, '$.name') INTO l_name FROM DUAL - 多字段建议一次查出:
SELECT JSON_VALUE(...), JSON_VALUE(...) INTO l_name, l_age FROM DUAL - 路径大小写敏感、键含空格需用双引号:
$.["order id"];数组必须显式写[*],$.tags不会展开为多行
JDBC 读取 JSON 列时 rs.getString() 会失败
这不是 PL/SQL 问题,但常被混淆——如果你从 Java 应用传入 JSON 到 19c 表中,再在 PL/SQL 里处理,第一步就可能卡住:用 rs.getString("col") 会抛异常或返回乱码(二进制 blob),因为 JDBC 驱动默认不把原生 JSON 类型转成字符串。
- 唯一可靠方式:
rs.getObject("col", String.class)(需 ojdbc8 ≥ 19.19) - 不要用
rs.getNString()、rs.getClob()或rs.getObject("col")(返回OracleJsonStructure,不能直接 toString) - 所谓 “OracleJsonValue 驱动” 不存在;
JSON_VALUE等是服务端函数,与驱动无关
最易被忽略的是路径的相对性和空值行为:NESTED PATH 的 $ 不指根,而指父级对象;不加 NULL ON EMPTY 时,任意一层缺失字段都会导致整行消失——这不像报错,而是静默丢数据。











