-------------------------------------------------------------------------------
-- ex_pl_ref_curseur.sql
-------------------------------------------------------------------------------

/*
certains buts d'un ref cursor :
- si une table(s) est encapsulee, une procedure privee peut evaluer une requete 
  dessus et en renvoyer le resultat, sans que l'appelant connaisse la table
- de plus l'appelant doit juste savoir parcourir un curseur, pas faire une
  requete
*/

--------------------------------------------------------------------------------
drop table loisir;
create table loisir(nom varchar2(10), age integer, activite varchar2(10));
insert into loisir values('Riton', 22, 'SGBD');
insert into loisir values('Rita', 21, 'tango');
insert into loisir values('Jeanne', 20, 'sieste');
insert into loisir values('Jean', 23, 'logique');
insert into loisir values('Lulu', 50, 'trompette');
select * from loisir;

set serveroutput on

--------------------------------------------------------------------------------
create or replace function ex_ref_cursor_fun(n int) return sys_refcursor is
    c sys_refcursor;
begin
    open c for              -- remplissage de c
        select nom, age
            from loisir
            where age < n;
    return c;               -- renvoi de la zone c
end;
/

create or replace procedure aff_ref_cursor(a loisir.age%type) is
    c sys_refcursor;
    x loisir.nom%type;  -- rem : il faut connaitre les colonnes du select 
    y loisir.age%type;
begin 
    -- remplace le open c :
    c := ex_ref_cursor_fun(a);   -- zone renvoyee par fonction mise dans c
                                 -- encapsulation respectee
    -- ex_ref_cursor_proc(n, c); -- pour variante ci-dessous via variable out
    loop                         -- parcours normal du curseur
        fetch c into x, y;
        exit when c%notfound;
	dbms_output.put_line(x||' '||y);
    end loop;
end;
/

exec aff_ref_cursor(30);

-------------------------------------------------------------------------------
-- ci-dessous variante avec variable out, pour s'entrainer, 
-- mais version ci-dessus avec fonction plus elegante

create or replace procedure ex_ref_cursor_proc (
    a loisir.age%type, 
    c out sys_refcursor) is
begin
    open c for 
        select nom, age
            from loisir
            where age < a;
end;
/

-------------------------------------------------------------------------------
-- exemple construit a partir de codes de Jesus Camacho-Rodriguez, 2012
-------------------------------------------------------------------------------
