sql >> Databáze >  >> RDS >> Oracle

Oracle FOR LOOP neopakuje v SYS_REFCURSOR

Všimněte si následujících rozšířených komentářů:

Možná je středem otázky nepochopení toho, co je kurzor. Není to kontejner plný záznamů, je to specifikace pro sadu výsledků, jako v určitém okamžiku, na základě jediného SQL dotazu. Pokud tedy

open rc for select id from table1;

a předejte rc zpět volajícímu, nepředáváte žádná data, předáváte ukazatel na oblast soukromé paměti obsahující připravený dotaz. Výsledky netlačíte, tahá je volající. Je to jako program, který volající spustí, aby načetl řádky. Nemůžete ho otevřít ani trochu víc a přidat další řádek, což je podle mě to, v co jste doufali.

Chcete-li použít kolekci v kurzoru v proceduře, typ kolekce musí být vytvořen jako samostatný objekt schématu (ačkoli samozřejmě můžete typy kolekce znovu použít v jiných procedurách, takže to není tak omezující, jak to zní).

Pokud nemůžete vytvořit typ, podívejte se, jaké typy již existují a můžete je použít:

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

Například:

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;

Nyní může být postup:

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;

Výstup kurzoru:

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

(Odstranil jsem i_id parametr ve vašem postupu, protože mi nebylo jasné, jak jej chcete použít.)

Pravděpodobně se jedná o zjednodušenou verzi skutečného problému, protože ve stávající podobě byste mohli použít první dotaz jako dílčí dotaz a nepotřebovali byste kolekci:

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;

nebo se k tomu prostě připojte, jak navrhl 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;

K této odpovědi jste však poznamenal, že to nemůžete udělat, protože se zdálo, že vaším požadavkem je udělat to pomocí sbírky, smyčky, nějaké lepicí pásky, dvou koček a fúzního generátoru.



  1. Jak nastavit časové razítko s časovým pásmem v Laravel 5 Migrate

  2. Převeďte datum ve formátu MM/DD/RRRR na datum MySQL

  3. PL/SQL FTP API binární vs režim ascii

  4. Jak zvýšit výkon vyhledávacího dotazu SQL?