In Oracle, reference cursor is a pointer to data, rather than data itself.
So if a procedure returns two reference cursors, the the client still has to go and fetch the rows from those cursors (and incur the network hits).
As such, if the data volumes are small, you probably want to call a procedure that just returns the values.
If the data volumes are large (thousands of rows) then it won't be a single network trip anyway, so an extra one or two as you switch between cursors isn't going to make much difference.
Another choice is have a single select return all the rows. That might be a simple UNION ALL
select a, b, c from y union all select d, e, f from z;
It could be a pipelined table function
create or replace package test_pkg is
type rec_two_cols is record
(col_a varchar2(100),
col_b varchar2(100));
type tab_two_cols is table of rec_two_cols;
function ret_two_cols return tab_two_cols pipelined;
end;
/
create or replace package body test_pkg is
function ret_two_cols return tab_two_cols pipelined
is
cursor c_1 is select 'type 1' col_a, object_name col_b from user_objects;
cursor c_2 is select 'type 2' col_a, object_name col_b from user_objects;
r_two_cols rec_two_cols;
begin
for c_rec in c_1 loop
r_two_cols.col_a := c_rec.col_a;
r_two_cols.col_b := c_rec.col_b;
pipe row (r_two_cols);
end loop;
for c_rec in c_2 loop
r_two_cols.col_a := c_rec.col_a;
r_two_cols.col_b := c_rec.col_b;
pipe row (r_two_cols);
end loop;
return;
end;
end;
/
select * from table(test_pkg.ret_two_cols);
I believe the most recent versions of ODP for 11g allow user-defined types which may help.