如何通过其他过程将多个refcursor返回到另一个过程

时间:2017-04-12 11:47:08

标签: sql postgresql postgresql-9.4

我有一个返回setof游标的程序
现在我必须将该过程调用到另一个过程并访问数据 通过该程序返回 他们是什么方式在postgres做到这一点。 这是第一个程序的代码,

    CREATE OR REPLACE FUNCTION public.returns_multiple_cursor( )
        RETURNS SETOF refcursor 
        LANGUAGE 'plpgsql'
        COST 100.0

    AS $function$

    DECLARE
        _daily refcursor := 'first_cur';
        _fac_hourly refcursor := 'second_cur';
    BEGIN

        open first_cur for  
        select * from x;
        return next first_cur;

        open second_cur for 
        select * from y;
        return  second_cur;

    END 
    $function$;
    ALTER FUNCTION public.returns_multiple_cursor();

这里是其他第二个程序的代码

    CREATE OR REPLACE FUNCTION public.access_cursor( )
    RETURNS SETOF refcursor 
    LANGUAGE 'plpgsql'
    COST 100.0

    AS $function$

    DECLARE

    BEGIN

    -- what code will be here to access the cursor data in this procedure

    select public.returns_multiple_cursor();

    END;
    ALTER FUNCTION public.access_cursor();

1 个答案:

答案 0 :(得分:0)

不幸的是,你不能使用FOR <recordvar> IN <cursor>循环,因为它只适用于绑定游标(refcursor不是)。

但你仍然可以使用老式的FETCH

来遍历它们
declare
  rec record;
  cur refcursor;
begin
  for cur in select returns_multiple_cursor() loop
    loop
      fetch next from cur into rec;
      exit when not found;
      -- do whatever you want with the single rows here
    end loop;
    close cur;
  end loop;
end

不幸的是,还有另一个限制:PostgreSQL缓存了第一个游标的计划(至少,似乎它做了类似的事情),所以你必须使用游标,它使用相同的列类型(你&#39 ; ll必须使用相同的列名,以便能够在内循环中引用它们,如rec.col1)。

完整的,有效的示例:http://rextester.com/FNWG91106(请参阅f.ex.当您从游标&#39;查询中删除投射时会发生什么。)

如果你有固定游标数量(如你的例子),但结构不同的底层查询,可能更容易将returns_multiple_cursor声明为:

create or replace  function returns_multiple_cursor(out first_cur refcursor,
                                                    out second_cur refcursor)
    -- returns record (optional)
    language plpgsql
-- ...

这样,您可以在调用上下文中更直接地访问游标。

更新:似乎当您不使用显式列名称,只是通用记录处理(通过f.ex.JSON或hstore)时,计划缓存不会造成任何麻烦:

http://rextester.com/QHR6096