Как в fetch получить один столбец из курсора, для которого нельзя указать %rowtype?
Пишу процедуру, в которой получаю курсор из другой процедуры.
Нужно с помощью fetch получить первый столбец из курсора. Так как там много столбцов, то не желательно бы заводить переменную под каждую, чтобы не было такого:
fetch into v1, v2, v3, v4, v5, v6, v7, v8
А так:
row_set v_cursor%rowtype;
не получается сделать, потому что объявление курсора находится в другой процедуре.
bulk collect я не пробовал, но в курсоре возвращаются разные типы, а он, как я понимаю, может вернуть только в массив.
Ответы (2 шт):
Создайте пакет и поместите объявление курсора в тело пакета.
Это будет выглядеть примерно как в воиспроизводимом примере ниже:
create or replace package pack1 as
procedure process;
end;
/
create or replace package body pack1 as
cursor cur1 is
select 1 col1, 2 col2, 3 col3 from dual union all
select 4 col1, 5 col2, 6 col3 from dual;
type currows is table of cur1%rowtype;
procedure openCursor is
begin
open cur1;
end;
function fetchCursor return currows is
ret currows;
begin
fetch cur1 bulk collect into ret;
close cur1;
return ret;
end;
procedure process is
rs currows;
begin
openCursor;
rs := fetchCursor ();
for i in 1..rs.count loop
dbms_output.put_line ('col2['||i||']='||rs(i).col2);
end loop;
end;
end;
/
Запуск и результат:
exec pack1.process;
col2[1]=2
col2[2]=5
Автор вопроса прокомментировал:
А как сделать, чтобы эта процедура именно возвращала курсор?
Oбъявленный в PL/SQL явный курсор нельзя вeрнуть из процедуры или функции. Вернуть можно только курсор с типом REF CURSOR. Эти типы несовместимы, т.е. нельзя переменную явного курсора присвоить переменной курсора. Но можно обрабатывать явный курсор в табличной функции, а её результат возвращать как курсор.
Посмотрите, как это сделать:
create or replace package pack2 as
cursor cur1 is
select 1 col1, 2 col2, 3 col3 from dual union all
select 4 col1, 5 col2, 6 col3 from dual;
type currows is table of cur1%rowtype;
type refcursor is ref cursor return cur1%rowtype;
procedure process;
procedure opencur (rc out refcursor);
function getdata return currows pipelined;
end;
/
create or replace package body pack2 as
function getdata return currows pipelined is
begin
for r in cur1 loop pipe row (r);
end loop;
return;
end;
procedure opencur (rc out refcursor) is
begin
open rc for select * from table (getdata ());
end;
procedure process is
rc refcursor;
rs currows;
begin
opencur (rc);
fetch rc bulk collect into rs;
for i in 1..rs.count loop
dbms_output.put_line ('col2['||i||']='||rs(i).col2);
end loop;
end;
end;
/
Такое решение будет работать внутри блока и с ним можно вернуть откртый курсор:
exec pack2.process;
col2[1]=2
col2[2]=5
var rc refcursor
exec pack2.opencur (:rc);
COL1 COL2 COL3
---------- ---------- ----------
1 2 3
4 5 6