web-dev-qa-db-fra.com

Comment renvoyer plusieurs lignes de la procédure stockée? (Oracle PL / SQL)

Je veux créer une procédure stockée avec un argument qui renverra différents ensembles d'enregistrements en fonction de l'argument. Quel est le moyen de faire cela? Puis-je l'appeler à partir de SQL pur?

46
Aleksey

Voici comment créer une fonction qui retourne un jeu de résultats pouvant être interrogé comme s'il s'agissait d'une table:

SQL> create type emp_obj is object (empno number, ename varchar2(10));
  2  /

Type created.

SQL> create type emp_tab is table of emp_obj;
  2  /

Type created.

SQL> create or replace function all_emps return emp_tab
  2  is
  3     l_emp_tab emp_tab := emp_tab();
  4     n integer := 0;
  5  begin
  6     for r in (select empno, ename from emp)
  7     loop
  8        l_emp_tab.extend;
  9        n := n + 1;
 10       l_emp_tab(n) := emp_obj(r.empno, r.ename);
 11     end loop;
 12     return l_emp_tab;
 13  end;
 14  /

Function created.

SQL> select * from table (all_emps);

     EMPNO ENAME
---------- ----------
      7369 SMITH
      7499 ALLEN
      7521 WARD
      7566 JONES
      7654 MARTIN
      7698 BLAKE
      7782 CLARK
      7788 SCOTT
      7839 KING
      7844 TURNER
      7902 FORD
      7934 MILLER
65
Tony Andrews

Je pense que vous voulez retourner un REFCURSEUR:

create function test_cursor 
            return sys_refcursor
            is
                    c_result sys_refcursor;
            begin
                    open c_result for
                    select * from dual;
                    return c_result;
            end;

Mise à jour: Si vous devez appeler cela à partir de SQL, utilisez une fonction de table comme celle suggérée par @Tony Andrews.

22
Thilo

Vous pouvez utiliser des fonctions en pipeline Oracle

En gros, quand vous voulez qu'une routine PLSQL (ou Java ou c) soit la "source" des données - au lieu d'une table - vous utiliserez une fonction en pipeline.

Exemple simple - Génération de données aléatoires
Comment pourriez-vous créer N nombres aléatoires uniques en fonction de l'argument d'entrée?

create type array
as table of number;


create function  gen_numbers(n in number default null)
return array
PIPELINED
as
begin
  for i in 1 .. nvl(n,999999999)
  loop
     pipe row(i);
 end loop;
 return;
end;

Supposons que nous ayons besoin de trois lignes pour quelque chose. Nous pouvons maintenant le faire de deux manières:

select * from TABLE(gen_numbers(3));

COLUMN_VALUE


       1
       2
       3

ou

select * from TABLE(gen_numbers)
 where rownum <= 3;

COLUMN_VALUE


       1
       2
       3

Fonctions en pipeline 1Fonctions en pipeline 2

8
Mohsen Heydari

Si vous voulez l'utiliser en langage SQL simple, je laisserais la procédure de stockage remplir une table ou une table temporaire avec les lignes résultantes (ou choisir l'approche @Tony Andrews).
Si vous voulez utiliser la solution de @ Thilo, vous devez boucler le curseur avec PL/SQL. Voici un exemple: (J'ai utilisé une procédure à la place d'une fonction, comme l'a fait @Thilo)

create or replace procedure myprocedure(retval in out sys_refcursor) is
begin
  open retval for
    select TABLE_NAME from user_tables;
end myprocedure;

 declare 
   myrefcur sys_refcursor;
   tablename user_tables.TABLE_NAME%type;
 begin
   myprocedure(myrefcur);
   loop
     fetch myrefcur into tablename;
     exit when myrefcur%notfound;
     dbms_output.put_line(tablename);
   end loop;
   close myrefcur;
 end;
3
John Smithers
create procedure <procedure_name>(p_cur out sys_refcursor) as begin open p_cur for select * from <table_name> end;
1
S. Mayol