如何通过其他程序将多个 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
), 计划缓存不会造成任何麻烦:
我有一个程序 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
), 计划缓存不会造成任何麻烦: