Oracle11g 合并两个sys\u refcursor的输出

Oracle11g 合并两个sys\u refcursor的输出,oracle11g,merge,cursor,Oracle11g,Merge,Cursor,我在Oracle11g中有两个函数,它们返回一个sys\u 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_REFC

我在Oracle11g中有两个函数,它们返回一个sys\u 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;
第一个funzion的输出示例如下

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

没有简单的内置机制来合并ref游标;它们本质上是指向结果集的指针,它们不能被视为表,因此它们不能被连接,这就是您在这里试图实现的

如果只想显示组合结果,可以使用PL/SQL集合存储第一个ref游标的结果,然后根据
leg
作为公共“键”值,使用第二个ref游标的结果对其进行更新/添加:

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 collection元素中为游标拥有的列设置值;其中,在这两种情况下,索引都是
leg

第一个循环填充索引17和18处记录元素的
leg
gettoni
值。第二个只看到18的结果,并为该元素设置
interrogazioni
。如果它也有一个不同的
leg
,比如说19,那么它也会用
leg
interrogazioni
值填充一个索引元素。(因此,本质上,它大致相当于一个完整的外部连接…)

但是依靠
dbms\u输出
进行输出并不理想,因为您无法控制客户机是否在使用它,而且更难格式化和使用它。将结果作为可在查询中使用的表集合或作为新的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;
/
这里的
num\u combo\u tab
基本上是上面的匿名块,但它通过管道传输记录类型,而不是使用
dbms\u输出
。然后,
num\u combo\u cur
只为该结果打开一个ref光标

那么你可以做:

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
来代替现有函数声明其参数的方式。

不容易。谁或什么人将使用合并的结果?这些函数是独立的还是在一个包中?此过程的唯一任务是调用这些函数以显示结果。现在,这些函数是独立的。如果您更简单,可以假设这些函数在一个包中
select * from table(num_combo_tab('MRTMRZ'));

       LEG    GETTONI INTERROGAZIONI
---------- ---------- --------------
        17          3               
        18          2              1