PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Declarando a estrutura de tupla de um registro em PL/pgSQL


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 , onde some_type pode ser qualquer tipo escalar ou composto registrado.

  • TABLE (col1 type1, col2 type2) - uma definição de tipo de linha ad hoc.

  • SETOF record mais OUT parâmetros para definir nomes e tipos de coluna.
    100% equivalente a RETURNS TABLE .

  • SETOF record sem 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 TABLE ou 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.