Esta es el arreglo más correcta que te podemos dar, sin embargo obsérvala detenidamente y analiza si es compatible a tu proyecto.
Solución:
La función necesita devolver un SETOF RECORD
en vez de RECORD
y tener uno RETURN NEXT
por fila en lugar de una sola RETURN
como en:
CREATE FUNCTION test() RETURNS SETOF RECORD AS $$
DECLARE
rec record;
BEGIN
select 1,2 into rec;
return next rec;
select 3,4 into rec;
return next rec;
END $$ language plpgsql;
Llamador:
=> select * from test() as x(a int ,b int) ; a | b ---+--- 1 | 2 3 | 4 (2 rows)
Tenga en cuenta que SQL está tipificado fuerte y estáticamente, el RECORD
pseudo-tipo es difícil de trabajar.
A menudo, es menos engorroso utilizar desde el principio un tipo compuesto con una definición completa de nombres y tipos para cada columna, ya sea con el TABLE(...)
sintaxis para un tipo anónimo o con CREATE TYPE
para un tipo persistente con nombre.
Usar setof record
y return next rec
si desea devolver varios registros de una función, ejemplo:
create or replace function test_function()
returns setof record
language plpgsql as $$
declare
rec record;
begin
for rec in
select i, format('str%s', i), i/2*2 = i
from generate_series(1, 3) i
loop
return next rec;
end loop;
end $$;
Dicha función debe llamarse en la cláusula FROM con una lista de definición de columna:
select test_function(); -- NO
ERROR: set-valued function called in context that cannot accept a set
select * from test_function(); -- NO
ERROR: a column definition list is required for functions returning "record"
select * from test_function() as (id int, str text, is_even boolean);
id | str | is_even
----+------+---------
1 | str1 | f
2 | str2 | t
3 | str3 | f
(3 rows)
Una mejor opción es usar returns table(...)
y return query
:
drop function if exists test_function();
create or replace function test_function()
returns table (id int, str text, is_even boolean)
language plpgsql as $$
begin
return query
select i, format('str%s', i), i/2*2 = i
from generate_series(1, 3) i;
-- you can use return query multiple times
-- or assign values to columns
-- and return the row:
id = 100;
str = 'extra';
is_even = true;
return next; -- without a parameter
end $$;
Uso:
select test_function(); -- possible but rather impractical
test_function
---------------
(1,str1,f)
(2,str2,t)
(3,str3,f)
(100,extra,t)
(4 rows)
select * from test_function();
id | str | is_even
-----+-------+---------
1 | str1 | f
2 | str2 | t
3 | str3 | f
100 | extra | t
(4 rows)
valoraciones y comentarios
Si entiendes que ha resultado de utilidad nuestro post, sería de mucha ayuda si lo compartes con el resto entusiastas de la programación de esta manera nos ayudas a extender este contenido.