sql >> Database teknologi >  >> RDS >> Oracle

oracle FOR LOOP itererer ikke i SYS_REFCURSOR

Bemærk følgende udvidede kommentarer:

Måske i centrum af spørgsmålet er en misforståelse af, hvad en markør er. Det er ikke en beholder fuld af poster, det er en specifikation for et resultatsæt, som på et tidspunkt, baseret på en enkelt SQL-forespørgsel. Så hvis du

open rc for select id from table1;

og send rc tilbage til den, der ringer, sender du ingen data, du sender en pegepind til et privat hukommelsesområde, der indeholder en forberedt forespørgsel. Du presser ikke resultaterne, den, der ringer, trækker dem. Det er ligesom et program, som den, der ringer, vil udføre for at hente rækkerne. Du kan ikke åbne den lidt mere for at tilføje endnu en række, hvilket jeg tror er, hvad du håbede på at gøre.

For at bruge en samling i en markør i en procedure, skal samlingstypen oprettes som et separat skemaobjekt (selvom du selvfølgelig kan genbruge samlingstyper i andre procedurer, så det er ikke så restriktivt, som det lyder).

Hvis du ikke kan oprette en type, kan du se, hvilke typer der allerede findes, som du kan bruge:

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

For eksempel:

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;

Nu kan proceduren være:

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;

Markørudgang:

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

(Jeg fjernede i_id parameter i din procedure, da jeg ikke var klar over, hvordan du ville bruge den.)

Formentlig er dette en forenklet version af det faktiske problem, for som det står, kan du bruge den første forespørgsel som en underforespørgsel, og du har ikke brug for samlingen:

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;

eller bare slutte sig til det, som Littlefoot foreslog:

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;

Du kommenterede dog på det svar, at du ikke kunne gøre det, fordi dit krav så ud til at være at gøre det via en samling, en løkke, noget gaffatape, to katte og en fusionsgenerator.



  1. Problem med Oracle-dataadgangsversion

  2. MySQL-fejl ved forsøg på at afkorte tabel

  3. får syntaksfejl ved oprettelse af funktion

  4. (Postgresql) få tabeludløserfunktion til at indsætte ID-værdi for ændret række i logtabel, til tilpasset replikering