oracle json_value 返回 null 的根本原因是其仅支持返回单个标量值,路径指向数组、对象、不存在字段或输入为 null 时均静默返回 null。

直接说结论:Oracle JSON_VALUE 返回 NULL,绝大多数情况不是函数写错了,而是路径没匹配到标量值、输入为 NULL、或路径指向了数组/对象——它只认单个标量。
为什么 JSON_VALUE 总是返回 NULL?
根本原因在于 JSON_VALUE 的语义限制:它**必须返回一个标量值(string/number/boolean)**,且路径表达式必须精准命中该标量。一旦路径指向的是数组、对象、不存在的字段,或原始 JSON 字段本身为 NULL,默认行为就是静默返回 NULL(而非报错)。
- 路径写成
'$.items'→ 指向数组 →NULL - 路径写成
'$.address'→ 指向对象 →NULL - 源字段值为
NULL→ 直接返回NULL(Oracle 12c 还可能引发重复行 bug) - 路径大小写/下划线不匹配(如 JSON 是
{"pin_code":"123"},却查'$.pinCode')→ 找不到 →NULL
JSON_VALUE 路径指向数组时怎么处理?
不能硬用 JSON_VALUE 提数组——它不支持。必须换函数或改写法:
- 想取数组第一个元素的某个字段?用
JSON_VALUE(json_col, '$.items[0].name')(前提是items确实是数组且有第 0 项) - 想展开整个数组?用
JSON_TABLE,例如:SELECT jt.name FROM t, JSON_TABLE(t.json_col, '$.items[*]' COLUMNS (name VARCHAR2(100) PATH '$.name')) jt - 只想判断是否存在数组?用
JSON_EXISTS(t.json_col, '$.items'),返回TRUE/FALSE - 别用
JSON_EXTRACT或json_col.items语法替代JSON_VALUE——它们行为不同,且在老版本 Oracle 中可能不支持
如何让 NULL 输入不导致结果异常或重复?
Oracle 12c–19c 中,JSON_VALUE(NULL, '$.x') 不仅返回 NULL,还可能在多列同时使用时触发重复记录 bug(尤其配合 GROUP BY 或视图)。稳妥做法是提前兜底:
- 用
NVL或COALESCE替换空值:JSON_VALUE(NVL(json_col, '{}'), '$.code') - 用
ON EMPTY显式控制空路径行为:JSON_VALUE(json_col, '$.code' DEFAULT 'N/A' ON EMPTY) - 用
ON ERROR捕获解析失败(比如 JSON 格式损坏):JSON_VALUE(json_col, '$.code' DEFAULT 'ERROR' ON ERROR) - 注意:
ON EMPTY和ON ERROR是独立开关,建议两个都配,避免静默失效
JDBC 里读不到 JSON 列内容,误以为是 JSON_VALUE 问题?
这是常见混淆点:JSON_VALUE 是 SQL 层函数,和 JDBC 读取原生 JSON 列无关。如果你在 Java 里调用 rs.getString("json_col") 得到乱码或报错,问题不在 SQL 函数,而在驱动读取方式:
- Oracle 19c+ 原生 JSON 列必须用
rs.getObject("json_col", String.class),不能用getString() - 驱动必须是
ojdbc8 ≥ 19.19(即 ojdbc8u3+),旧版根本不识别SQLType.JSON - 所谓 “OracleJsonValue 驱动” 不存在——那是把服务端函数名当成客户端驱动名了
真正容易被忽略的是:JSON 路径是否真的存在标量值,以及 NULL 输入在多列 JSON_VALUE 场景下的副作用。别急着改路径,先 SELECT json_col FROM t WHERE ... 看一眼原始数据长什么样。










