如何通过其他程序将多个 refcursor return 读取到另一个程序

How to read multiple refcursor return by other procedure to another procedure

我有一个程序 returns setof 游标
现在我必须将该过程调用到另一个过程并访问数据 return 通过那个程序 是他们在 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();

不幸的是,您不能使用 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 缓存了第一个游标的计划(至少,它似乎做了类似的事情),所以你必须使用游标,它使用相同的列类型(你必须无论如何都使用相同的列名,以便能够在内部循环中引用它们,例如 rec.col1).

完整的工作示例:http://rextester.com/FNWG91106(参见 f.ex。当您从游标的查询中删除转换时会发生什么)。

如果您有固定数量的游标(如您的示例),但底层查询结构不同,则将您的 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