【问题标题】:How to open multiple cursors with main cursor data如何使用主游标数据打开多个游标
【发布时间】:2020-08-11 07:47:00
【问题描述】:

我正在尝试读取从另一个存储过程返回的存储过程中的游标,并希望通过循环访问主游标数据来写入多个输出游标。

-- 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;

当我在循环中打开游标时,它将仅返回 localaccountdetails 游标的最后一行详细信息。我不确定如何使用 BUILK COLLECT 收集所有内容并在其上循环。

而且我不知道如何将 localaccountdetails 作为 OUT 数据返回并循环它以获取剩余数据。

【问题讨论】:

  • 你打算用你的游标结果做什么?
  • Java 程序将读取所有这些游标
  • 所以你需要重新考虑你是如何做到这一点的。您不能遍历游标并期望输出主查询中有许多行的游标,并期望它们全部传递给Java
  • 你可能会发现你需要带上localaccountdetails游标并合并到fundscur和其他detailscur游标中,例如select ... from fundstable f inner join <cursor's select statement> c on f.accountnumber = c.accountnumber
  • pkgaccount.accountdetails 有很多逻辑可以返回 localaccountdetails 光标,所以我尝试使用相同的东西而不是复制它。

标签: sql oracle plsql database-cursor


【解决方案1】:

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

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

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

如果您想确保从父表中获取一行,您可以将内部表的行聚合到 JSON 或嵌套表中,例如:

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}]  

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-28
    • 2012-12-03
    • 2017-07-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多