Oracle
 sql >> Baza danych >  >> RDS >> Oracle

oracle FOR LOOP nie wykonuje iteracji w SYS_REFCURSOR

Uwaga po komentarzach rozszerzonych:

Być może w centrum pytania jest niezrozumienie, czym jest kursor. Nie jest to kontener pełen rekordów, to specyfikacja zbioru wyników, jak w danym momencie, na podstawie pojedynczego zapytania SQL. Więc jeśli

open rc for select id from table1;

i przekaż rc z powrotem do dzwoniącego, nie przekazujesz żadnych danych, przekazujesz wskaźnik do prywatnego obszaru pamięci zawierającego przygotowane zapytanie. Nie popychasz wyników, dzwoniący je wyciąga. To jest jak program, który wywoła wywołujący, aby pobrać wiersze. Nie możesz otworzyć go trochę bardziej, aby dodać kolejny wiersz, co myślę, że masz nadzieję zrobić.

Aby użyć kolekcji w kursorze w ramach procedury, typ kolekcji musi być utworzony jako oddzielny obiekt schematu (chociaż oczywiście można ponownie użyć typów kolekcji w innych procedurach, więc nie jest to tak restrykcyjne, jak się wydaje).

Jeśli nie możesz utworzyć typu, zobacz, jakie typy już istnieją, których możesz użyć:

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

Na przykład:

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;

Teraz procedura może wyglądać następująco:

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;

Wyjście kursora:

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

(Usunąłem i_id w twojej procedurze, ponieważ nie wiedziałem, jak chcesz go użyć.)

Przypuszczalnie jest to uproszczona wersja aktualnego problemu, ponieważ w obecnej postaci możesz użyć pierwszego zapytania jako podzapytania i nie potrzebujesz kolekcji:

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;

lub po prostu dołącz do niego, jak zasugerował 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;

Jednak skomentowałeś tę odpowiedź, że nie możesz tego zrobić, ponieważ wydawało się, że musisz to zrobić za pomocą kolekcji, pętli, taśmy izolacyjnej, dwóch kotów i generatora termojądrowego.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Wykrywanie przyrostowych zmian w bazie danych (od Oracle do MongoDB ETL)

  2. simpleJdbcCall wywołująca procedurę Pl/SQL -- ORA-22922 nieistniejąca wartość LOB

  3. Oracle odejmowanie dni i minut

  4. Jak wstawić BLOB do Oracle za pomocą Pythona?

  5. Błąd składni Oracle