Нет простого встроенного механизма для объединения ref-курсоров; по сути, они являются указателями на наборы результатов, и их нельзя рассматривать как таблицы, поэтому их нельзя объединять, чего, по сути, вы и здесь добиваетесь.
Если вы просто хотите отобразить объединенные результаты, вы можете использовать коллекцию PL / SQL для хранения результатов из первого курсора ссылки, а затем обновить / добавить к нему результаты второго, исходя из того, что leg
является общее значение ключа:
declare
-- for the collection
type t_rec is record (leg number, gettoni number, interrogazioni number);
type t_tab is table of t_rec index by pls_integer;
l_tab t_tab;
-- for the cursors returned by the functions
l_cursor sys_refcursor;
-- for the individual columns from the cursors
l_leg number;
l_gettoni number;
l_interrogazioni number;
begin
l_cursor := num_gettoni('MRTMRZ');
loop
fetch l_cursor into l_leg, l_gettoni;
exit when l_cursor%notfound;
l_tab(l_leg).leg := l_leg;
l_tab(l_leg).gettoni := l_gettoni;
end loop;
close l_cursor;
l_cursor := num_interrogazioni('MRTMRZ');
loop
fetch l_cursor into l_leg, l_interrogazioni;
exit when l_cursor%notfound;
l_tab(l_leg).leg := l_leg;
l_tab(l_leg).interrogazioni := l_interrogazioni;
end loop;
close l_cursor;
for i in l_tab.first..l_tab.last loop
dbms_output.put_line(l_tab(i).leg ||','|| l_tab(i).gettoni ||','|| l_tab(i).interrogazioni);
end loop;
end;
/
который с фиктивными функциями, возвращающими результаты, которые вы показали, получает:
17,3,
18,2,1
PL/SQL procedure successfully completed.
Два цикла курсора по сути одинаковы. Вызовите соответствующую функцию и переберите результаты, установив значения в элементе коллекции index-by для столбцов, которые имеет курсор; где в обоих случаях индексом является значение leg
.
Первый цикл заполняет значения leg
и gettoni
для элементов записи по индексам 17 и 18. Второй просматривает результат только для 18 и устанавливает interrogazioni
для этого элемента. Если бы это также имело другой leg
, скажем, 19, то он также заполнил бы элемент с этим индексом значениями leg
и interrogazioni
. (Так что, по сути, это примерно эквивалентно полному внешнему объединению ...)
Но полагаться на dbms_output
для вывода не идеально, так как вы не контролируете, использует ли это клиент, и его сложнее форматировать и потреблять. Вероятно, было бы более полезно вернуть результат в виде коллекции таблиц, которую можно использовать в запросе, или, возможно, в качестве нового курсора ref.
Вы можете использовать пакет для определения типов коллекций, при этом функция, использующая механизм, описанный выше, помещает результаты в виде коллекции таблиц, и вторая функция, которая генерирует курсор ref из этой переданной по конвейеру таблицы:
create or replace package p42 as
type t_rec is record (leg number, gettoni number, interrogazioni number);
type t_tab is table of t_rec;
-- function for pipelined table collection
function num_combo_tab (p_param varchar2) return t_tab pipelined;
-- function for ref cursor
function num_combo_cur (p_param varchar2) return sys_refcursor;
end p42;
/
create or replace package body p42 as
-- function for pipelined table collection
function num_combo_tab (p_param varchar2) return t_tab pipelined is
type t_tmp_tab is table of t_rec index by pls_integer;
l_tab t_tmp_tab;
l_leg number;
l_gettoni number;
l_interrogazioni number;
l_cursor sys_refcursor;
begin
l_cursor := num_gettoni(p_param);
loop
fetch l_cursor into l_leg, l_gettoni;
exit when l_cursor%notfound;
l_tab(l_leg).leg := l_leg;
l_tab(l_leg).gettoni := l_gettoni;
end loop;
close l_cursor;
l_cursor := num_interrogazioni(p_param);
loop
fetch l_cursor into l_leg, l_interrogazioni;
exit when l_cursor%notfound;
l_tab(l_leg).leg := l_leg;
l_tab(l_leg).interrogazioni := l_interrogazioni;
end loop;
close l_cursor;
for i in l_tab.first..l_tab.last loop
pipe row (l_tab(i));
end loop;
end num_combo_tab;
-- function for ref cursor
function num_combo_cur (p_param varchar2) return sys_refcursor is
l_cursor sys_refcursor;
begin
open l_cursor for
select * from table(num_combo_tab(p_param));
return l_cursor;
end num_combo_cur;
end p42;
/
Здесь num_combo_tab
- это в основном анонимный блок выше, но он передает тип записи вместо использования dbms_output
. И тогда num_combo_cur
просто открывает курсор ссылки для этого результата.
Итак, вы можете сделать:
select p42.num_combo_cur('MRTMRZ') from dual;
P42.NUM_COMBO_CUR('M
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
LEG GETTONI INTERROGAZIONI
---------- ---------- --------------
17 3
18 2 1
или просто используйте версию таблицы напрямую:
select * from table(p42.num_combo_tab('MRTMRZ'));
LEG GETTONI INTERROGAZIONI
---------- ---------- --------------
17 3
18 2 1
Вы также можете сделать это с типами объектов и таблиц уровня схемы и функцией уровня схемы, если вы предпочитаете:
create type t_obj as object (leg number, gettoni number, interrogazioni number)
/
create type t_tab is table of t_obj
/
create or replace function num_combo_tab (p_param varchar2)
return t_tab pipelined as
type t_tmp_tab is table of t_obj index by pls_integer;
l_tab t_tmp_tab;
l_leg number;
l_gettoni number;
l_interrogazioni number;
l_cursor sys_refcursor;
begin
l_cursor := num_gettoni(p_param);
loop
fetch l_cursor into l_leg, l_gettoni;
exit when l_cursor%notfound;
l_tab(l_leg) := new t_obj(l_leg, l_gettoni, null);
end loop;
close l_cursor;
l_cursor := num_interrogazioni(p_param);
loop
fetch l_cursor into l_leg, l_interrogazioni;
exit when l_cursor%notfound;
if l_tab.exists(l_leg) then
l_tab(l_leg).interrogazioni := l_interrogazioni;
else
l_tab(l_leg) := new t_obj(l_leg, null, l_interrogazioni);
end if;
end loop;
close l_cursor;
for i in l_tab.first..l_tab.last loop
pipe row (l_tab(i));
end loop;
end num_combo_tab;
/
тогда вы можете назвать это как:
select * from table(num_combo_tab('MRTMRZ'));
LEG GETTONI INTERROGAZIONI
---------- ---------- --------------
17 3
18 2 1
Но, вероятно, было бы разумнее иметь это, а также, возможно, ваши оригинальные функции в пакете.
Во всем вышеперечисленном, очевидно, используйте свои собственные типы данных и %type
, когда вы можете, у меня нет ваших таблиц, поэтому я использовал, например. p_param varchar
вместо того, как существующие функции объявляют свои параметры.