oracle 19c无原生json类型,仅支持varchar2/clob+json函数;21c引入原生json类型(oson二进制),支持pl/sql声明变量、点号访问、编译期校验及is json列约束。

JSON 类型本身在 19c 中并不存在,21c 才正式引入原生 JSON 数据类型 —— 这是 PL/SQL 处理 JSON 的分水岭。
19c 中没有 JSON 类型,只有 VARCHAR2/CLOB + 解析函数
19c 不支持声明 JSON 类型变量或列,所有 JSON 数据必须用 VARCHAR2(4000)、VARCHAR2(32767)(需 MAX_STRING_SIZE=EXTENDED)或 CLOB 存储。
-
JSON_OBJECT、JSON_ARRAY等构造函数可用,但返回的是VARCHAR2或CLOB,不是类型安全的 JSON 实体 -
JSON_VALUE、JSON_QUERY可用,但底层仍依赖字符串解析,不校验输入是否合法 JSON(比如传入'{a:1}'不报错,只是查不到值) - PL/SQL 中无法直接用
.操作符访问字段:json_var.name会报PLS-00302: component 'NAME' must be declared - 插入时无法强制校验:即使写
INSERT INTO t VALUES ('{invalid json');也不会被拦住,直到你调用IS JSON或解析时才暴露问题
21c 支持原生 JSON 类型,PL/SQL 可直接操作
21c 引入了真正的 JSON 数据类型(底层是 OSON 二进制格式),PL/SQL 可声明变量、参数、返回值,并启用点号访问和编译期校验。
- 可声明:
DECLARE j JSON := JSON('{ "name": "Alice", "age": 30 }'); - 支持点号访问:
DBMS_OUTPUT.PUT_LINE(j.name);→ 输出"Alice"(注意带引号) - 字段访问在编译期检查:若写
j.nonexistent_field,PL/SQL 编译直接报错PLS-00302: component 'NONEXISTENT_FIELD' must be declared - 赋值自动校验:
j := JSON('{ "x": }');在运行时抛出ORA-40442: JSON syntax error - 函数参数可类型化:
FUNCTION get_name(j JSON) RETURN VARCHAR2 IS ...,调用时传非 JSON 值会被拒绝
JSON 函数行为差异:从“尽力而为”到“严格校验”
同名函数如 JSON_VALUE 在两个版本中行为不同,关键在于输入是否被声明为 JSON 类型。
- 19c 中:
JSON_VALUE('{"a":1}', '$.a')接收任意字符串,不验证 JSON 合法性;若路径不存在,返回 NULL,无提示 - 21c 中:
JSON_VALUE(j, '$.a')(j是JSON类型)会在解析前确认其二进制结构有效;若路径非法,仍返回 NULL,但若输入本身不是 JSON,则在赋值给JSON变量时就已失败 -
IS JSON在 19c 是函数,在 21c 可作为列约束:CREATE TABLE t (j JSON CHECK (j IS JSON)),且约束在 INSERT/UPDATE 时实时触发
容易踩的坑:混用版本特性导致静默失败
最常见问题是把 21c 写法直接搬到 19c 环境,或误以为函数行为一致。
- 在 19c 执行
DECLARE j JSON := ...;→ 直接报错PLS-00201: identifier 'JSON' must be declared - 在 21c 使用
VARCHAR2存 JSON 并调用JSON_VALUE,看似正常,但失去类型保护和性能优势(OSON 二进制解析比字符串解析快) - 迁移脚本含
CHECK (col IS JSON),在 19c 会报ORA-00904: invalid identifier(因为 19c 不支持该语法作为约束) - 依赖
JSON类型的 JDBC 绑定(如setObject(idx, jsonValue, Types.OTHER))在 19c 驱动下可能回退为字符串,丢失结构信息










