我在oracle 11g中有两个函数,它们返回sys_refcursos。 第一个
create or replace FUNCTION num_gettoni
(cf_parlamentare IN parlamentari.cf %TYPE DEFAULT 'MRTMRZ'
--, num_legislatura in legislature.id%TYPE
) RETURN SYS_REFCURSOR
AS
my_cursor SYS_REFCURSOR;
pippo legislature.id%type;
BEGIN
OPEN my_cursor FOR
select
leg,
ct as gettoni
from(
SELECT
l.id AS leg,
COUNT(*) - lead(COUNT(*), 1, 0) over (order by l.datainizio) AS ct
FROM
legislature l,
partecipazioni i,
parlamentari p
WHERE
i.sedute_data >= l.datainizio
AND p.cf = i.parlamentare
AND p.cf = cf_parlamentare
group by l.datainizio, l.id
)
where ct > 0
order by ct desc;
/*open my_cursor;
loop
pippo := my_cursor.leg;
END LOOP;
end loop;*/
RETURN my_cursor;
END num_gettoni;
第一个函数的输出示例是
select num_gettoni('MRTMRZ') from dual;
NUM_GETTONI('MRTMRZ')
---------------------
LEG GETTONI
---------------------- ----------------------
17 3
18 2
第二个函数相似,第二个函数的输出是
select num_interrogazioni('MRTMRZ') from dual;
NUM_INTERROGAZIONI('MRTMRZ')
--------------------------------------
LEG INTERROGAZIONI
---------------------- ----------------------
18 1
是否可以通过一个过程调用这些函数,并在以下结果类似?
NUM_INTERROGAZIONI('MRTMRZ')
--------------------------------------
LEG GETTONI INTERROGAZIONI
---------------------- ---------------------- ----------------------
17 3
18 2 1
答案 0 :(得分:1)
没有简单的内置机制来合并引用游标;它们本质上是指向结果集的指针,并且不能将它们视为表,因此无法将它们连接在一起,这实际上是您要在此处实现的目标。
如果只想显示合并的结果,则可以使用PL / SQL集合存储第一个ref游标的结果,然后根据{{1}使用第二个游标的结果进行更新/添加。 }是常用的“键”值:
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;
/
两个光标循环本质上是相同的。调用相关函数并循环遍历结果,在index-by集合元素中为游标具有的列设置值;在两种情况下,索引都是17,3,
18,2,1
PL/SQL procedure successfully completed.
值。
第一个循环在索引17和18处填充记录元素的leg
和leg
值。第二个循环仅看到18的结果并为该元素设置gettoni
。如果那也有一个不同的interrogazioni
,比如说19,那么它还将用同时包含leg
和leg
值的索引填充一个元素。 (因此,从本质上讲,它大致等同于完整的外部联接...)
但是,依靠interrogazioni
进行输出并不理想,因为您无法控制客户端是否正在使用该格式,并且格式化和使用更加困难。将结果作为可以在查询中使用的表集合或作为新的引用游标取回,可能会更有用。
您可以使用包来定义集合类型,使用上述函数的函数将结果通过管道传递到表集合中,使用第二个函数从该管道表中生成引用游标:
dbms_output
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
,而不是现有函数声明其参数的方式。