将 JSON_ARRAY_T 转换为 SQL 表达式的表达式列表

Converting JSON_ARRAY_T to expression list for SQL expression

在 PL/SQL 中,我可以从有效负载中读取并获取 JSON_ARRAY_T 对象。假设我想查询由 id 标识的文档列表。 payload中发送的JSON为:

{"id": [1, 2, 3]}

我的PL/SQL会像

DECLARE 
    payload JSON_OBJECT_T;
    idArray JSON_ARRAY_T;
    cur SYS_REFCURSOR;
BEGIN
    payload := JSON_OBJECT_T.parse(:body_text);
    
    idArray := payload.get_Array('id');

    OPEN cur FOR
        SELECT * FROM INVOICES WHERE id IN idArray;
    :result := cur;
END;

我遇到一个错误,但是说 ORA-00932: inconsistent datatypes: expected NUMBER got SYS.JSON_ARRAY_T。我应该如何让它工作?

使用 JSON_TABLE 在 SQL 中全部完成:

BEGIN
  OPEN :result FOR
    SELECT i.*
    FROM   INVOICES i
           INNER JOIN JSON_TABLE(
             :body_text,
             '$.id[*]'
             ERROR ON ERROR
             COLUMNS (
               id NUMBER PATH '$'
             )
           ) j
           ON (i.id = j.id);
END;
/

db<>fiddle here

这里的问题是“in”子句期望右侧有一个列表,但无法处理 json_array_t 实例。

一个选项是将数组展开为数字。为了做到这一点,“in”子句的右侧参数将是 json_table 的结果,它将输入数组展开。

drop table invoices;
create table invoices (id number);

insert into invoices values (2);
insert into invoices values (4);

select * from invoices where id in 
(select * from json_table('{"id":[1,2,3]}', '$.id[*]' columns (a path '$')));

另一种方法是将 json_array 转换为 varray/nested table 并在“in”子句的右侧展开。同上,但需要 varray/nested table 作为中间步骤。

drop table invoices;
create table invoices (id number);

insert into invoices values (2);
insert into invoices values (4);

drop type narr;
create type narr as array(5) of number;
/

select * from invoices where id in
 (select * from table
   (select json_value('{"id":[1,2,3]}', '$.id' returning narr)));

就是说,如果您想继续使用 json_array_t,那么您可能想像这样迭代 json_array_t 的元素:

DECLARE 
    payload JSON_OBJECT_T;
    idArray JSON_ARRAY_T;
    idx number;
BEGIN
    payload := JSON_OBJECT_T.parse('{"id":[1,2,3]}');
    
    idArray := payload.get_Array('id');

    for idx in 1..idArray.get_Size loop
      dbms_output.put_line(idArray.get(idx-1).to_Number());
    end loop;
END;
/