JSON_OBJECT是Oracle 19c的SQL函数,不能在PL/SQL块中直接调用;必须通过SELECT ... INTO方式使用,并配合JSON_SERIALIZE转换为字符串,且19c不支持直接声明JSON类型变量。

JSON_OBJECT在PL/SQL中不能直接返回字符串
Oracle 19c 的 JSON_OBJECT 是 SQL 函数,不是 PL/SQL 内置函数。你在 PL/SQL 块里写 JSON_OBJECT('name', 'alice') 会报错:ORA-00904: “JSON_OBJECT”: invalid identifier。它只在 SQL 上下文(如 SELECT、INSERT、WITH 子句)中有效。
常见错误现象:DECLARE j CLOB; BEGIN j := JSON_OBJECT('id', 1); END; → 编译失败。
- 必须用
SELECT JSON_OBJECT(...) INTO ... FROM DUAL方式调用 - 返回类型是 Oracle 原生
JSON类型(Oracle 19c+),不是 VARCHAR2 或 CLOB —— 即使看起来像字符串,也不能直接拼接或赋值给字符串变量 - 若需字符串形式,必须显式用
JSON_SERIALIZE包裹,例如:SELECT JSON_SERIALIZE(JSON_OBJECT('x', 1)) INTO v_str FROM DUAL;
用JSON_OBJECT(*)生成整行JSON时注意列名大小写
JSON_OBJECT(*) 在 PL/SQL 中只能通过动态 SQL 或嵌套查询使用,且列名会原样转为 JSON key —— 包括大小写和空格。比如表中有列 "DeptName"(带双引号定义的标识符),JSON_OBJECT(*) 输出的 key 就是 "DeptName",而不是默认大写的 "DEPTNAME"。
典型场景:导出某张配置表为 JSON 配置片段。
- 确保源表列名符合预期风格;若想统一小写,得显式列出列并 alias:
JSON_OBJECT(deptno AS 'deptno', dname AS 'dname', loc AS 'loc') - 别在
JSON_OBJECT(*)后直接接JSON_SERIALIZE而不加括号包裹,否则解析失败:JSON_SERIALIZE(JSON_OBJECT(*))✅,JSON_SERIALIZE(JSON_OBJECT(*)) FORMAT JSON更稳妥 - 如果表含 BLOB/CLOB/DATE 等非标量类型,
JSON_OBJECT(*)会报 ORA-40473:需先用TO_CHAR、UTL_RAW.CAST_TO_VARCHAR2等转成 JSON 支持类型
在动态SQL中拼接JSON_OBJECT要防SQL注入
当键名或值来自变量时,不能简单字符串拼接:'JSON_OBJECT(''' || key_name || ''', ''' || val || ')' —— 这会导致单引号逃逸问题,且无法处理 NULL、数字、布尔等类型。
正确做法是用绑定变量 + EXECUTE IMMEDIATE ... USING,但注意:JSON_OBJECT 不接受绑定变量作为 key 名,只支持 value 绑定。
- key 必须是字面量或列名,不能是变量;value 可绑定:
EXECUTE IMMEDIATE 'SELECT JSON_OBJECT(''id'', :1, ''active'', :2) FROM DUAL' INTO j USING 123, 'true'; - 若 key 也需动态,得用字符串拼接 +
DBMS_ASSERT.SIMPLE_SQL_NAME校验:DBMS_ASSERT.SIMPLE_SQL_NAME(key_var)防止注入 - 拼接后建议用
DBMS_OUTPUT.PUT_LINE打印调试 SQL,再执行,避免语法错误卡在运行时
JSON_OBJECT生成的JSON类型不能直接赋给PL/SQL变量
即使你用 SELECT JSON_OBJECT(...) INTO v_json FROM DUAL,目标变量也不能声明为 VARCHAR2 或 CLOB —— Oracle 19c 默认把它当作原生 JSON 类型,而 PL/SQL 还不支持该类型的直接变量声明(直到 21c 才部分支持 JSON 类型变量)。
所以实际能用的只有两种路径:
- 声明为
CLOB,但必须走JSON_SERIALIZE:SELECT JSON_SERIALIZE(JSON_OBJECT('a', 1)) INTO v_clob FROM DUAL; - 声明为
JSON类型(仅限 Oracle 21c+),19c 会报 PLS-00201:identifier 'JSON' must be declared - 如果后续要传给 Java 应用,别省略
FORMAT JSON—— 否则JSON_SERIALIZE可能输出带转义的字符串而非标准 JSON 文本
最易被忽略的一点:PL/SQL 里没有 JSON 解析器(不像 Java 有 Jackson),JSON_OBJECT 只负责构造,不提供 get_string、get_number 等方法;要查字段得回到 SQL 层用 JSON_VALUE 或开游标查子查询。


















