PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Déclarer la structure tuple d'un enregistrement en PL/pgSQL

Vous mélangez la syntaxe pour renvoyer SETOF valeurs avec la syntaxe pour renvoyer une seule ligne ou valeur.

-- Une question connexe est - comment puis-je renvoyer l'enregistrement unique 'r' de

Lorsque vous déclarez une fonction avec RETURNS TABLE , vous devez utiliser RETURN NEXT dans le corps pour renvoyer une ligne (ou une valeur scalaire). Et si vous souhaitez utiliser un record variable avec laquelle elle doit correspondre le type de retour. Reportez-vous aux exemples de code plus bas.

Renvoyer une seule valeur ou ligne

Si vous souhaitez simplement renvoyer une seule ligne, il n'y a pas besoin pour un enregistrement de type indéfini. @Kevin a déjà démontré deux façons. Je vais ajouter une version simplifiée avec OUT paramètres :

CREATE OR REPLACE FUNCTION my_func(OUT a integer, OUT b text)
   AS
$func$
BEGIN
   a := ...;
   b := ...;
END
$func$ LANGUAGE plpgsql;

Vous n'avez même pas besoin d'ajouter RETURN; dans le corps de la fonction, la valeur du OUT déclaré les paramètres seront retournés automatiquement à la fin de la fonction - NULL pour tout paramètre qui n'a pas été affecté.
Et vous n'avez pas besoin de déclarer RETURNS RECORD parce que c'est déjà clair depuis le OUT paramètres.

Renvoyer un ensemble de lignes

Si vous souhaitez réellement renvoyer plusieurs lignes (y compris la possibilité pour 0 ou 1 ligne), vous pouvez définir le type de retour comme RETURNS ...

  • SETOF some_type , où some_type peut être n'importe quel type scalaire ou composite enregistré.

  • TABLE (col1 type1, col2 type2) - une définition de type de ligne ad hoc.

  • SETOF record plus OUT paramètres pour définir les noms et les types de colonnes.
    100 % équivalent à RETURNS TABLE .

  • SETOF record sans autre définition. Mais alors les lignes renvoyées sont indéfinies et vous devez inclure une liste de définition de colonne avec chaque appel (voir exemple).

Le manuel sur le type d'enregistrement :

Les variables d'enregistrement sont similaires aux variables de type ligne, mais elles n'ont aucune structure prédéfinie. Ils prennent la structure de ligne réelle de la ligne qui leur est affectée lors d'une commande SELECT ou FOR.

Il y a plus, lire le manuel.

Vous pouvez utiliser une variable d'enregistrement sans affecter de type défini, vous pouvez renvoient même de tels enregistrements indéfinis :

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;

Appel :

SELECT * FROM my_func() AS x(a int, b text);

Mais c'est très difficile à manier car vous devez fournir la liste de définition de colonne avec chaque appel. Il peut généralement être remplacé par quelque chose de plus élégant :

  • Si vous connaissez le type au moment de la création de la fonction, déclarez-le tout de suite (RETURNS TABLE ou amis).

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;
  • Si vous connaissez le type au moment de l'appel de la fonction , il existe des manières plus élégantes d'utiliser les types polymorphes :
    Refactoriser une fonction PL/pgSQL pour renvoyer la sortie de diverses requêtes SELECT

Votre question n'est pas claire quant à ce dont vous avez besoin exactement.