Oracle
 sql >> база данни >  >> RDS >> Oracle

oracle FOR LOOP не итерира в SYS_REFCURSOR

Обърнете внимание на следните разширени коментари:

Може би в центъра на въпроса е неразбирането на това какво е курсор. Това не е контейнер, пълен със записи, това е спецификация за набор от резултати, както в даден момент, въз основа на една 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;

Вие обаче коментирахте този отговор, че не можете да направите това, защото вашето изискване изглежда беше да го направите чрез колекция, контур, малко тиксо, две котки и термоядрен генератор.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Какво е еквивалентът на SQL Server APPLY в Oracle?

  2. Как да създадете и използвате списък с множество избори в APEX ORACLE?

  3. Как да получите списък с месеци между 2 дадени дати с помощта на заявка?

  4. Функция Oracle за актуализиране на таблица, ако записът е нулев, тогава INSERT

  5. SQL изисква самостоятелно присъединяване и класиране