sql >> Database >  >> RDS >> Oracle

oracle FOR LOOP herhaalt zich niet in SYS_REFCURSOR

Let op de volgende uitgebreide opmerkingen:

Misschien is de kern van de vraag een misverstand over wat een cursor is. Het is geen container vol records, het is een specificatie voor een resultatenset, zoals op een bepaald moment, op basis van een enkele SQL-query. Dus als je

open rc for select id from table1;

en geef rc door terug naar de beller, u geeft geen gegevens door, u geeft een aanwijzer door naar een privégeheugengebied met een voorbereide vraag. U pusht de resultaten niet, de beller trekt ze. Het is als een programma dat de beller zal uitvoeren om de rijen op te halen. Je kunt het niet verder openen om nog een rij toe te voegen, wat volgens mij is wat je hoopte te doen.

Om een ​​verzameling in een cursor binnen een procedure te gebruiken, moet het verzamelingstype worden gemaakt als een afzonderlijk schema-object (hoewel u verzamelingstypen natuurlijk opnieuw kunt gebruiken in andere procedures, dus het is niet zo beperkend als het klinkt).

Als je geen type kunt maken, kijk dan welke typen al bestaan ​​die je kunt gebruiken:

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

Bijvoorbeeld:

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 de procedure zijn:

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;

Cursoruitvoer:

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

(Ik heb de i_id verwijderd parameter in uw procedure omdat ik niet duidelijk was hoe u deze wilde gebruiken.)

Vermoedelijk is dit een vereenvoudigde versie van het eigenlijke probleem, want zoals het er nu uitziet zou je de eerste query als een subquery kunnen gebruiken en zou je de verzameling niet nodig hebben:

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;

of doe gewoon mee, zoals Littlefoot suggereerde:

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;

U gaf echter aan dat u dat niet kon doen omdat uw vereiste leek te zijn om het te doen via een verzameling, een lus, wat ducttape, twee katten en een fusiegenerator.



  1. Laravel join-query's AS

  2. Uitdagingsoplossingen voor generatorreeksen - deel 2

  3. MySQL fulltext met stengels

  4. gebruik LIKE en IN met subquery in sql