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
plusOUT
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.