You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Oracle存储过程中动态遍历JSON响应并插入数据的问题

解决Oracle中动态遍历JSON对象并插入表的问题

嘿,作为Oracle新手碰到JSON遍历的难题太正常了,别慌!你想要的是自动遍历JSON里data对象的所有键值对,不用手动写每个键就能插入表中,对吧?我给你两种常见场景的解决方案,你可以根据自己的表结构来选:


场景1:表是「键值对存储」(推荐)

如果你的TABLE_NAME是用来存键和对应值的(比如有KEY_NAMEKEY_VALUE两列),那用JSON_TABLE直接做集合插入最高效,完全不需要循环:

首先先纠正你原来插入语句的语法问题——Oracle里INSERT的列名不能加单引号,正确的静态写法应该是:

INSERT INTO TABLE_NAME (KEY_NAME, KEY_VALUE)
VALUES ('KEY_ONE', json_value(JSON_TEXT_DATA, '$.data.Key_One'));

现在改成动态遍历的版本:

CREATE OR REPLACE PROCEDURE TEST(JSON_TEXT_DATA IN CLOB) AS
BEGIN
  -- 用JSON_TABLE解析data下的所有键值对,直接插入表
  INSERT INTO TABLE_NAME (KEY_NAME, KEY_VALUE)
  SELECT 
    UPPER(key_name), -- 转成大写匹配Oracle列名(可选,根据你的实际情况调整)
    key_value
  FROM JSON_TABLE(
    JSON_TEXT_DATA,
    '$.data.*' COLUMNS (
      key_name PATH '$."key"',  -- 提取JSON里的键名
      key_value PATH '$."value"' -- 提取对应的值
    )
  );
  
  COMMIT; -- 按需提交,也可以交给调用方处理
END;
/

代码说明:

  • JSON_TABLE是Oracle 12c+支持的JSON解析工具,'$.data.*'表示遍历data对象下的所有成员;
  • PATH '$."key"'PATH '$."value"'分别把每个键值对拆成键名和值,变成表的一行;
  • UPPER(key_name)是因为Oracle列名默认是大写的,如果你的JSON键是驼峰式(比如Key_one),转成大写后就能匹配表的列名(比如KEY_ONE)。

场景2:表的列名对应JSON的键

如果你的TABLE_NAME的列名和JSON里的键一一对应(比如表有KEY_ONEKEY_TWO列,要把Key_one的值插入KEY_ONE列),那需要用动态SQL来生成插入语句:

CREATE OR REPLACE PROCEDURE TEST(JSON_TEXT_DATA IN CLOB) AS
  TYPE KeyValueList IS TABLE OF VARCHAR2(2000);
  v_keys KeyValueList;    -- 存所有JSON键名
  v_values KeyValueList;  -- 存对应的值
  v_sql VARCHAR2(4000);
BEGIN
  -- 先把所有键值对收集到集合里
  SELECT 
    UPPER(key_name),
    key_value
  BULK COLLECT INTO v_keys, v_values
  FROM JSON_TABLE(
    JSON_TEXT_DATA,
    '$.data.*' COLUMNS (
      key_name PATH '$."key"',
      key_value PATH '$."value"'
    )
  );
  
  -- 拼接动态INSERT语句
  v_sql := 'INSERT INTO TABLE_NAME (' || 
           LISTAGG(v_keys(i), ', ') WITHIN GROUP (ORDER BY i) || 
           ') VALUES (' || 
           LISTAGG('''' || REPLACE(v_values(i), '''', '''''') || '''', ', ') WITHIN GROUP (ORDER BY i) || 
           ')';
  
  -- 执行动态SQL
  EXECUTE IMMEDIATE v_sql;
  COMMIT;
EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE('出错啦:' || SQLERRM);
    RAISE; -- 把错误抛出去,方便调试
END;
/

代码说明:

  • BULK COLLECT把JSON解析后的键和值批量存入集合,避免逐行循环;
  • LISTAGG用来拼接列名和值列表,生成完整的INSERT语句;
  • REPLACE(v_values(i), '''', '''''')是为了转义值里的单引号,防止SQL语法错误。

内容的提问来源于stack exchange,提问作者tony

火山引擎 最新活动