如何用主游标数据打开多个游标

How to open multiple cursors with main cursor data

我正在尝试从另一个存储过程 return 中读取存储过程中的游标,并希望通过遍历主游标数据来写入多个输出游标。

-- TYPE myCursorType IS REF CURSOR;
PROCEDURE prcgetalldetails (
    incustomernumber    IN customer.customer_number%TYPE,
    accountdetailscur   OUT pkgaccount.curaccountdetailstype,
    fundscur            OUT mycursortype,
    otherdetailscur     OUT mycursortype
) IS
    localaccountdetails   pkgaccount.curinvestmentaccount;
    outcfunds             curinvestmentaccount;
    accountdetails        pkgaccount.curaccountdetailstype%rowtype;
BEGIN
    pkgaccount.accountdetails(incustomernumber,localaccountdetails);
    LOOP
        FETCH localaccountdetails INTO accountdetails;
        EXIT WHEN localaccountdetails%notfound;
        dbms_output.put_line(localaccountdetails.accountname
         || ','
         || localaccountdetails.accountnumber);
        
        -- I have to return the 'accountdetailscur' as well,before that I have to loop through it and return remaining data as well
        -- Based on account number I have to execute other queries and fetch other details and give those cursors back
        OPEN fundscur FOR
            SELECT
                fundname,
                fundid,
                fundbalance
            FROM
                fundstable
            WHERE
                accountnumber = localaccountdetails.accountnumber;

        OPEN otherdetailscur FOR
            SELECT
                col1,
                col2
            FROM
                othertable
            WHERE
                accountnumber = localaccountdetails.accountnumber;

    END LOOP;

END;

由于我在循环中打开游标,它 return 只会显示 localaccountdetails 游标的最后一行详细信息。我不确定如何使用 BUILK COLLECT 来收集所有内容并在其上循环。

而且我不知道如何return localaccountdetails 作为 OUT 数据并循环获取剩余数据。

您可以使用游标表达式将一个游标嵌套在另一个游标中。这是以下形式:

select cursor ( select ... ) from ...

所以你可以这样做:

create table par ( pk primary key ) as 
  select level pk
  from   dual
  connect by level <= 5;
  
create table chd as 
  select r.c1 pk, par.pk fk 
  from   par, lateral ( 
    select level c1 from dual
    connect by level <= pk
  ) r;
  
select pk,
       cursor (
         select * from chd c
         where  par.pk = c.fk
       )
from   par;

declare
  cursor cur is 
    select pk,
           cursor (
             select * from chd c
             where  par.pk = c.fk
           )
    from   par;
  
  pk      integer;
  chd_cur sys_refcursor;
  type chd_arr is table of chd%rowtype
    index by pls_integer;
  chd_recs chd_arr;
begin
  open cur;
  loop
    fetch cur into pk, chd_cur;
    exit when cur%notfound;
    
    fetch chd_cur bulk collect into chd_recs;
    dbms_output.put_line ( 
      'Fetched ' || pk || ' child rows ' || chd_recs.count 
    );
  end loop;
  close cur;
end;
/

Fetched 1 child rows 1
Fetched 2 child rows 2
Fetched 3 child rows 3
Fetched 4 child rows 4
Fetched 5 child rows 5

请注意,这意味着您正在滚动自己的嵌套循环连接。除非你真的 需要控制客户端从 child/inner table 中获取多少行,否则我会将其设为连接。

如果要确保从父 table 获得一行,可以将内部 table 的行聚合到 JSON 或嵌套 table,例如:

select par.pk,
       json_arrayagg ( 
         json_object ( chd.* ) 
       )
from   par
join   chd
on     par.pk = chd.fk
group  by par.pk;

PK    JSON_ARRAYAGG(JSON_OBJECT(CHD.*))                                                   
    1 [{"PK":1,"FK":1}]                                                                    
    2 [{"PK":1,"FK":2},{"PK":2,"FK":2}]                                                    
    3 [{"PK":1,"FK":3},{"PK":3,"FK":3},{"PK":2,"FK":3}]                                    
    4 [{"PK":1,"FK":4},{"PK":4,"FK":4},{"PK":3,"FK":4},{"PK":2,"FK":4}]                    
    5 [{"PK":1,"FK":5},{"PK":5,"FK":5},{"PK":4,"FK":5},{"PK":3,"FK":5},{"PK":2,"FK":5}]