Você está misturando a sintaxe para retornar
SETOF valores com sintaxe para retornar uma única linha ou valor.
-- Uma questão relacionada é - como faço para retornar o registro único 'r' de
Quando você declara uma função com
RETURNS TABLE , você deve usar RETURN NEXT no corpo para retornar uma linha (ou valor escalar). E se você quiser usar um record variável com a qual tem que corresponder o tipo de retorno. Consulte os exemplos de código mais abaixo. Retorne um único valor ou linha
Se você deseja retornar apenas uma única linha, não há necessidade para um registro de tipo indefinido. @Kevin já demonstrou duas maneiras. Vou adicionar uma versão simplificada com
OUT parâmetros:CREATE OR REPLACE FUNCTION my_func(OUT a integer, OUT b text)
AS
$func$
BEGIN
a := ...;
b := ...;
END
$func$ LANGUAGE plpgsql;
Você nem precisa adicionar
RETURN; no corpo da função, o valor do OUT declarado parâmetros serão retornados automaticamente no final da função - NULL para qualquer parâmetro que não tenha sido atribuído.E você não precisa declarar
RETURNS RECORD porque isso já está claro no OUT parâmetros. Retorne um conjunto de linhas
Se você realmente deseja retornar múltiplos linhas (incluindo a possibilidade de 0 ou 1 linha), você pode definir o tipo de retorno como
RETURNS ... -
SETOF some_type, ondesome_typepode ser qualquer tipo escalar ou composto registrado.
-
TABLE (col1 type1, col2 type2)- uma definição de tipo de linha ad hoc.
-
SETOF recordmaisOUTparâmetros para definir nomes e tipos de coluna.
100% equivalente aRETURNS TABLE.
-
SETOF recordsem mais definição. Mas as linhas retornadas são indefinidas e você precisa incluir uma lista de definição de coluna com cada chamada (veja o exemplo).
O manual sobre o tipo de registro:
As variáveis de registro são semelhantes às variáveis do tipo linha, mas não têm estrutura predefinida. Eles assumem a estrutura de linha real da linha atribuída durante um comando SELECT ou FOR.
Há mais, leia o manual.
Você pode usar uma variável de registro sem atribuir um tipo definido, você pode até mesmo retornar esses registros indefinidos:
CREATE OR REPLACE FUNCTION my_func()
RETURNS SETOF record AS
$func$
DECLARE
r record;
BEGIN
r := (1::int, 'foo'::text); RETURN NEXT r; -- works with undefined record
r := (2::int, 'bar'::text); RETURN NEXT r;
END
$func$ LANGUAGE plpgsql;
Ligar:
SELECT * FROM my_func() AS x(a int, b text);
Mas isso é muito complicado pois você precisa fornecer a lista de definição de coluna com cada chamada. Geralmente pode ser substituído por algo mais elegante:
- Se você souber o tipo no momento da criação da função, declare-o imediatamente (
RETURNS TABLEou amigos).
CREATE OR REPLACE FUNCTION my_func()
RETURNS SETOF tbl_or_type AS
$func$
DECLARE
r tbl_or_type;
BEGIN
SELECT INTO tbl_or_type * FROM tbl WHERE id = 10;
RETURN NEXT r; -- type matches
SELECT INTO tbl_or_type * FROM tbl WHERE id = 12;
RETURN NEXT r;
-- Or simpler:
RETURN QUERY
SELECT * FROM tbl WHERE id = 14;
END
$func$ LANGUAGE plpgsql;
- Se você souber o tipo no momento da chamada da função , existem maneiras mais elegantes de usar tipos polimórficos:
Refatorar uma função PL/pgSQL para retornar a saída de várias consultas SELECT
Sua pergunta não está clara quanto ao que você precisa exatamente.