如何使用 PL/SQL 循环遍历 json 响应?

Posted

技术标签:

【中文标题】如何使用 PL/SQL 循环遍历 json 响应?【英文标题】:How to loop through a json response with PL/SQL? 【发布时间】:2020-05-29 08:27:07 【问题描述】:

当我的 json 响应如下时,我遇到了一个问题:

declare
sample_json   varchar2 (32767)
        := '"items": ["NAME":"AUDI","YEAR":"2000","NAME":"BMW","YEAR":"2010"]';
BEGIN
for rec IN (
     select j.name,j.year 
       from json_table(sample_json,'$[*]' COLUMNS 
        name varchar2(20) PATH '$.items[0].NAME',
        year NUMBER       PATH '$.items[0].YEAR'
       ) j  ) 
     LOOP
       dbms_output.put_line (rec.name||','||rec.year);
     END LOOP;
END;
/

我必须使用 $.items[0].NAME 来获取一个值,但我想让它动态化,以便它可以循环给我两个值。

【问题讨论】:

【参考方案1】:

也可以在纯 PL/SQL 中进行解析。考虑以下可重现的示例:

declare
    jdoc varchar2 (32767) := 
        '"items": ["NAME":"AUDI","YEAR":"2000","NAME":"BMW","YEAR":"2010"]';
    jobj json_object_t;
    keys json_key_list;
    jarr json_array_t;
begin
    jobj := json_object_t (jdoc);
    keys := jobj.get_keys;
    jarr := jobj.get_array (keys(1));
    for ai in 0..jarr.get_size ()-1 loop
        jobj := treat (jarr.get(ai) as json_object_t);
        keys := jobj.get_keys;
        for ki in 1..keys.count loop
            dbms_output.put_line (keys(ki)||'='||jobj.get_string (keys(ki)));
        end loop;
    end loop;
end;
/
PL/SQL procedure successfully completed.

NAME=AUDI
YEAR=2000
NAME=BMW
YEAR=2010

【讨论】:

【参考方案2】:

我无法完全理解您对使查询动态化的需求,但也许下面的脚本可以让您对使用 JSON_VALUE 和编写动态 plsql 语句有所了解。

DECLARE
   SAMPLE_JSON     VARCHAR2 (32767)
      := '"items": ["NAME":"AUDI","YEAR":"2000","NAME":"BMW","YEAR":"2010"]';
   V_RESULT_NAME   VARCHAR2 (500);
   V_RESULT_YEAR   VARCHAR2 (500);
   V_KEY           VARCHAR (200) := 'items[0].NAME';
   V_KEY2          VARCHAR (200) := 'items[0].YEAR';
BEGIN
   EXECUTE IMMEDIATE 'SELECT JSON_VALUE(:1,''$.' || V_KEY || ''')  FROM DUAL'
      INTO V_RESULT_NAME
      USING SAMPLE_JSON;

   DBMS_OUTPUT.PUT_LINE (V_RESULT_NAME );
END;
/

您可以在此处将 json 数据中的值动态插入到您的表中。

DECLARE
SAMPLE_JSON   VARCHAR2 (32767)
        := '"items": ["NAME":"AUDI","YEAR":"2000","NAME":"BMW","YEAR":"2010"]';
BEGIN
FOR REC IN (
     SELECT J.NAME,J.YEAR 
       FROM JSON_TABLE(SAMPLE_JSON,'$[*]' COLUMNS 
        NAME VARCHAR2(20) PATH '$.items[0].NAME',
        YEAR NUMBER       PATH '$.items[0].YEAR'
       ) J  ) 
     LOOP
     EXECUTE IMMEDIATE 'INSERT INTO YOUR_TABLE(NAME,YEAR) VALUES('||REC.NAME||','||REC.YEAR||'); COMMIT;'
--       DBMS_OUTPUT.PUT_LINE (REC.NAME||','||REC.YEAR);
     END LOOP;
END;
/

不使用索引。

DECLARE
SAMPLE_JSON   VARCHAR2 (32767)
        := '"items": ["NAME":"AUDI","YEAR":"2000","NAME":"BMW","YEAR":"2010","NAME":"TOFAS","YEAR":"1995"]';
BEGIN
FOR REC IN (
     SELECT J.NAME,J.YEAR 
       FROM JSON_TABLE(SAMPLE_JSON,'$.items[*]' COLUMNS 
        NAME VARCHAR2(20) PATH '$.NAME',
        YEAR NUMBER       PATH '$.YEAR'
       ) J  ) 
     LOOP
     --EXECUTE IMMEDIATE 'INSERT INTO YOUR_TABLE(NAMEE,YEARR) VALUES('||REC.NAME||','||REC.YEAR||'); COMMIT;';
      DBMS_OUTPUT.PUT_LINE (REC.NAME||','||REC.YEAR);
     END LOOP;
END;
/

注意:如果您想动态描述 json 数据中的列,我知道 oracle 无法做到这一点。使用前必须将 json 标签一一描述为 JSON_TABLE 列。

【讨论】:

要求基本上是遍历json响应,以便我们可以插入到数据库表中。上面只是示例示例,我们可以有 10-20 个 json 对象作为响应,我们需要循环以便获取数据库表中的所有 NAME、YEAR 列。 但是你的问题已经有了一个很好的循环 json 数据的方法。为什么你不能使用你已经拥有的?看看我编辑了我的答案。 @Vikash 是的,但这只会给我作为 AUDI,2000 的输出。由于路径具有硬编码索引 $.items[0].NAME。那么想象一下 10 条这样的记录?我想要一种可以获得所有值的方法。 那你为什么还要坚持使用[0]。您可以通过我的第三次编辑来实现您的目标。检查出。 @Vikash

以上是关于如何使用 PL/SQL 循环遍历 json 响应?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 PHP 循环遍历 JSON 数组

JavaScript中循环遍历JSON响应!

PL/SQL:循环遍历 XML 列并从重复元素中提取值

JavaScript中循环遍历JSON响应!

似乎找不到循环遍历 PL/SQL 数组的方法?

pl/sql 循环遍历表并将行的每个条目传递给存储过程