Вот простая функция, которая динамически открывает переменную курсора, используя переданный параметр имени таблицы.
create or replace function get_details_by_dno
( p_tab in user_tables.table_name%type
, p_dno in dept.deptno%type )
return sys_refcursor
is
rv sys_refcursor;
stmt varchar2(32767);
begin
stmt := 'select * from '
||p_tab
||' where deptno = :1';
open rv for stmt using p_dno;
return rv;
end;
/
Он также использует DEPTNO в качестве фильтра; следовательно, функция завершится ошибкой , если мы передадим таблицу, у которой нет такого столбца
Некоторые клиенты могут интерпретировать метаданные ref-курсора. Например, JDBC и ODBC ResultSets могут сделать это. SQL * Plus может сделать это:
SQL> exec :rc := get_details_by_dno('DEPT', 50)
PL/SQL procedure successfully completed.
SQL> print rc
DEPTNO DNAME LOC REGION
---------- -------------- ------------- ----------
50 HOUSEKEEPING INTERNAL
SQL> exec :rc := get_details_by_dno('EMP', 50)
PL/SQL procedure successfully completed.
SQL> exec :rc := get_details_by_dno('EMP', 50)
PL/SQL procedure successfully completed.
SQL> print rc
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
8085 TRICHLER PLUMBER 8061 08-APR-10 3500 50
8060 VERREYNNE PLUMBER 8061 08-APR-08 4000 50
8061 FEUERSTEIN PLUMBER 7839 27-FEB-10 4500 50
8100 PODER PLUMBER 8061 3750 50
SQL>
PL / SQL не может этого сделать. Поэтому нам нужно четко указать имена таблиц и столбцов.
create or replace procedure print_details_by_dno
( p_tab in user_tables.table_name%type
, p_dno in dept.deptno%type )
is
rc sys_refcursor;
emp_rec emp%rowtype;
dept_rec dept%rowtype;
begin
rc := get_details_by_dno( p_tab , p_dno );
if p_tab = 'EMP' then
fetch rc into emp_rec;
while rc%found loop
dbms_output.put_line('ename='||emp_rec.ename||' empno='||emp_rec.empno);
fetch rc into emp_rec;
end loop;
elsif p_tab = 'DEPT' then
fetch rc into dept_rec;
while rc%found loop
dbms_output.put_line('dname='||dept_rec.dname);
fetch rc into dept_rec;
end loop;
end if;
end;
/
Давайте посмотрим, как это работает:
SQL> set serveroutput on
SQL> exec print_details_by_dno('EMP',50)
ename=TRICHLER empno=8085
ename=VERREYNNE empno=8060
ename=FEUERSTEIN empno=8061
ename=PODER empno=8100
PL/SQL procedure successfully completed.
SQL> exec print_details_by_dno('DEPT',50)
dname=HOUSEKEEPING
PL/SQL procedure successfully completed.
SQL>