1

这是程序:

  1. 打开游标,然后通过批量收集获取选择查询的输出。
  2. 问题是所有 ID 都存储在批量收集中,但我无法通过使用批量收集变量作为输入来循环第二个选择查询,它只考虑第一个 ID 而不是全部。
  3. OUTPUT 应该是 SYS_REFCURSOR,请说明我在这里缺少什么

表1的测试数据:

ID 货币 T_ID
10 英镑 PB1
15 英镑 RB
20 英镑 抄送
25 澳元 直流

基于 t_id 我正在获取相应的 ID,然后在进一步的 select for 循环语句中使用这些 ID。

PROC 通过 SYS_REFCURSOR 的当前输出:

ID 国家 帐户
10 英国 PB1

预期输出:

ID 国家 帐户
10 英国 PB1
15 威尔士 RB
20 上海 抄送
create or replace procedure myproc (i_id in varchar2, rc out sys_refcursor)
as
    cursor names_cur is
        select id from table1 where currency='GBP' and t_id=i_id;
    names_t names_cur%ROWTYPE;
    type names_ntt is table of names_t%TYPE;
    l_names names_ntt;
begin
    open names_cur;
    fetch names_cur bulk collect into l_names ; --Inside l_names (10,15 & 20) would be stored 
    close names_cur;
--iSSUE IS WITH BELOW FOR LOOP
    for cur in l_names.first..l_names.last loop
        open rc for --For the below select I want to iterate l_names so for the above scenario it should iterate thrice

        select s.id,s.country,s.account from table2 s where s.id=l_names(cur).id;
    end loop;

end myproc;
4

2 回答 2

3

请注意以下扩展评论:

也许问题的中心是对光标是什么的误解。它不是一个装满记录的容器,它是一个结果集的规范,在某个时间点,基于单个 SQL 查询。所以如果你

open rc for select id from table1;

并传rc回给调用者,你没有传递任何数据,你传递的是一个指向包含准备好的查询的私有内存区域的指针。你不推结果,调用者拉他们。这就像调用者将执行以获取行的程序。你不能再打开它来添加另一行,我认为这是你希望做的。


要在过程中的游标中使用集合,必须将集合类型创建为单独的模式对象(当然,您可以在其他过程中重用集合类型,因此它不像听起来那么严格)。

如果您无法创建类型,请查看哪些类型已经存在您可以使用:

select owner, type_name
from   all_coll_types t
where  t.coll_type = 'TABLE'
and    t.elem_type_name = 'NUMBER';

例如:

create or replace type number_tt as table of number;

create table table1 (id primary key, currency, t_id) as
    select 10, 'GBP', 'PB1' from dual union all
    select 15, 'GBP', 'RB' from dual union all
    select 20, 'GBP', 'CC' from dual union all
    select 25, 'AUD', 'DC' from dual;

create table table2 (id,country,account) as
    select 10, 'UK', 'PB1' from dual union all
    select 15, 'Wales', 'RB' from dual union all
    select 20, 'SH', 'CC' from dual;

现在程序可以是:

create or replace procedure myproc
    ( rc out sys_refcursor)
as
    l_names number_tt;
begin
    select id bulk collect into l_names
    from   table1
    where  currency = 'GBP';

    open rc for
        select t.id,t.country,t.account from table2 t
        where  t.id member of l_names;
end myproc;

光标输出:

        ID COUNT ACC
---------- ----- ---
        10 UK    PB1
        15 Wales RB
        20 SH    CC

(我在你的过程中删除了i_id参数,因为我不清楚你想如何使用它。)

大概这是实际问题的简化版本,因为就目前而言,您可以将第一个查询用作子查询,并且不需要集合:

create or replace procedure myproc
    ( rc out sys_refcursor)
as
begin
    open rc for
        select t.id,t.country,t.account from table2 t
        where  t.id in
               ( select id 
                 from   table1
                 where  currency = 'GBP' );
end myproc;

或者只是加入它,就像 Littlefoot 建议的那样:

create or replace procedure myproc
    ( rc out sys_refcursor)
as
begin
    open rc for
        select t2.id, t2.country, t2.account
        from   table1 t1
               join table2 t2 on t2.id = t1.id
        where  t1.currency = 'GBP';
end myproc;

但是,您对该答案发表评论说您不能这样做,因为您的要求似乎是通过一个集合、一个循环、一些胶带、两只猫和一个融合发生器来做到这一点。

于 2021-03-13T09:57:17.243 回答
1

你需要光标做什么?以及过程的IN参数(因为您从未使用过它)?

反正:

create or replace procedure myproc (i_id in varchar2, rc out sys_refcursor)
  as
begin
  open rc
    select t.id,
           t.country,
           t.account 
    from table2 t join table1 a on a.id = t.id
    where a.currency = 'GBP';
end;
于 2021-03-12T18:12:42.873 回答