在 PLSQL 12.1 中循环 JSON 数组

Loop through JSON array in PLSQL 12.1

我在 varchar

中有 JSON 数组
DECLARE
 JsonArray varchar2(1000);
 arrayCars varchar2(1000);      
BEGIN
  JsonArray :={"Cars": [{"name":"Honda", "color":"red" },
                        {"name":"Toyota", "color":"green"}] }
  SELECT JSON_QUERY(JsonArray, '$.Cars') into arrayCars FROM dual;
END;
/

现在,如果我打印出 arrayCars,我将得到

[{"name":"Honda","color":"red"},{"name":"Toyota","color":"green"}]

但是我如何遍历这个 Cars 数组并分别打印出它的组件(访问它们)?

您可以直接使用SQLJSON_TABLE()功能,Oracle DB 12.1.0.2版本开始可用,例如

WITH t(arrayCars) AS
(
 SELECT JSON_QUERY('{"Cars": [{"name":"Honda", "color":"red" }, 
                              {"name":"Toyota", "color":"green"}] }', '$.Cars') 
   FROM dual
)
SELECT name, color
  FROM t
 CROSS JOIN JSON_TABLE(arrayCars,
                       '$' COLUMNS(NESTED PATH '$[*]'
                                    COLUMNS(
                                            name  VARCHAR2(100) PATH '$.name',
                                            color VARCHAR2(100) PATH '$.color'
                                            )
                                  )
          );

Demo

如果你真的需要使用PL/SQL,那么考虑创建一个SYS_REFCURSORreturn类型的函数,比如

CREATE OR REPLACE FUNCTION Get_Cars RETURN SYS_REFCURSOR IS
  v_recordset SYS_REFCURSOR;
  JsonArray   VARCHAR2(1000);
  arrayCars   VARCHAR2(1000);
  v_sql       VARCHAR2(32767);  
BEGIN
  JsonArray :='{"Cars": [{"name":"Honda", "color":"red" },
                         {"name":"Toyota", "color":"green"}] }';
  arrayCars := JSON_QUERY(JsonArray, '$.Cars');
  DBMS_OUTPUT.PUT_LINE(arrayCars);

  v_sql := 
  'SELECT name,color
     FROM dual
    CROSS JOIN JSON_TABLE(:Cars,
                          ''$'' COLUMNS(NESTED PATH ''$[*]''
                                      COLUMNS(
                                              name  VARCHAR2(100) PATH ''$.name'',
                                              color VARCHAR2(100) PATH ''$.color''
                                              )
                                    )

            )';
  OPEN v_recordset FOR v_sql USING arrayCars;
  RETURN v_recordset;
END;
/

然后从 SQL 开发者控制台调用

SQL> DECLARE
    result SYS_REFCURSOR;
BEGIN
   :result := Get_Cars;
END;
/

SQL> PRINT result ;

编辑(你最后的评论):

或者,您可以使用简单的隐式循环,例如

SQL> SET SERVEROUTPUT ON
SQL> DECLARE
  v_name   VARCHAR2(1000);
  v_color  VARCHAR2(1000);
BEGIN
   FOR c IN (
             SELECT name,color
               FROM JSON_TABLE('{"Cars": [{"name":"Honda", "color":"red" },
                                          {"name":"Toyota", "color":"green"}] }',
                                    '$' COLUMNS(NESTED PATH '$.Cars[*]'
                                                COLUMNS(
                                                        name  VARCHAR2(100) PATH '$.name',
                                                        color VARCHAR2(100) PATH '$.color'
                                                        )
                                                )
                               )
            )
   LOOP
     v_name  := c.name;
     v_color := c.color; 
     DBMS_OUTPUT.PUT_LINE(v_name||'  '||v_color);
   END LOOP;                            
END; 
/

Demo2