Fonction PostgreSQL ou procédure stockée qui produit plusieurs colonnes?

voici ce que je veux idéalement. Imaginez que j'ai une table avec la ligne .

je veux faire:

SELECT A, func(A) FROM table

et pour la sortie à avoir 4 colonnes.

Est-il possible de faire cela? J'ai vu des choses sur les types personnalisés ou n'importe quoi qui vous permettent de tri d'obtenir un résultat qui ressemblerait

A, (B,C, D)

mais ce serait vraiment génial si je pouvais avoir cette fonction retour plusieurs colonnes sans plus de finagling.

Est-il rien qui puisse faire quelque chose comme cela?

12
demandé sur informatik01 2011-03-28 21:49:30

4 réponses

Si la fonction func retourne seulement 1 rangée avec 3 valeurs, telles que:

CREATE OR REPLACE FUNCTION func
(
    input_val       integer,
    OUT output_val1 integer,
    OUT output_val2 integer,
    OUT output_val3 integer
)
AS $$
BEGIN
  output_val1 := input_val + 1;
  output_val2 := input_val + 2;
  output_val3 := input_val + 3;
END;
$$ LANGUAGE plpgsql;

et ensuite exécuter SELECT a, func(a) FROM table1 vous obtiendrez:

a       | func
integer | record
========|==========
1       | (2, 3, 4)
2       | (3, 4, 5)
3       | (4, 5, 6)

mais, si vous exécutez:

SELECT a, (f).output_val1, (f).output_val2, (f).output_val3
FROM (SELECT a, func(a) AS f FROM table1) AS x

vous obtiendrez:

a       | output_val1 | output_val2 | output_val3
integer | integer     | integer     | integer
========|=============|=============|=============
1       | 2           | 3           | 4
2       | 3           | 4           | 5
3       | 4           | 5           | 6

ou, à l'aide de CTE (Expressions de Table Communes), si vous exécutez le code suivant:

WITH temp AS (SELECT a, func(a) AS f FROM table1)
SELECT a, (f).output_val1, (f).output_val2, (f).output_val3 FROM temp

vous aurez également:

a       | output_val1 | output_val2 | output_val3
integer | integer     | integer     | integer
========|=============|=============|=============
1       | 2           | 3           | 4
2       | 3           | 4           | 5
3       | 4           | 5           | 6

Remarque: vous pouvez également utiliser les requêtes suivantes pour obtenir le même résultats:

SELECT a, (f).*
FROM (SELECT a, func(a) AS f FROM table1) AS x

ou

WITH temp AS (SELECT a, func(a) AS f FROM table1)
SELECT a, (f).* FROM temp
17
répondu bambam 2011-05-07 17:24:50

je suis d'accord avec la réponse de bambam mais je tiens à souligner que la syntaxe plus succincte de JackPDouglas SELECT a, (func(a)).* FROM table1, d'après mes tests, exécuterait en fait la fonction une fois pour chaque colonne retournée alors que l'expression CTE n'exécuterait la fonction qu'une fois. Ainsi, l'expression CTE est préférée si l'exécution de la fonction prend beaucoup de temps.

6
répondu ClubCranium 2011-06-02 20:24:02

Si la fonction renvoie toujours 3 colonnes, vous pouvez faire quelque chose comme ça:

CREATE TYPE sometype AS (b INT, c TEXT, d TEXT);

CREATE OR REPLACE FUNCTION func(a TEXT) RETURNS SETOF sometype AS $$
BEGIN
  RETURN QUERY EXECUTE 'SELECT b, c, d FROM ' || a;
END;
$$ LANGUAGE plpgsql;

SELECT a, (f).b, (f).c, (f).d 
FROM (SELECT a, func(a) AS f FROM table) x;

si vous pouvez accéder à la table depuis une vue, peut-être que vous pouvez créer une vue d'une certaine façon

CREATE VIEW v AS 
SELECT 'tab1' AS a, b, c, d FROM tab1 WHERE 'tab1' IN (SELECT a FROM table)
UNION
SELECT 'tab2' AS a, b, c, d FROM tab2 WHERE 'tab2' IN (SELECT a FROM table)
UNION
SELECT 'tab3' AS a, b, c, d FROM tab3 WHERE 'tab3' IN (SELECT a FROM table);

ensuite, c'est juste un SELECT * FROM v. Mais encore une fois, cela ressemble à Héritage pourrait être utilisé.

2
répondu rudi-moore 2011-03-29 18:43:05

je pense que vous aurez envie de revenir à un seul enregistrement, avec plusieurs colonnes? Dans ce cas, vous pouvez utiliser le type de retour RECORD par exemple. Cela vous permettra de retourner une variable anonyme avec autant de colonnes que vous le souhaitez. Vous trouverez plus d'informations sur toutes les variables ici:

http://www.postgresql.org/docs/9.0/static/plpgsql-declarations.html

et sur les types de retour:

http://www.postgresql.org/docs/9.0/static/xfunc-sql.html#XFUNC-OUTPUT-PARAMETERS

Si vous souhaitez retourner plusieurs enregistrements avec plusieurs colonnes, de vérifier et voir si vous avez à utiliser une procédure stockée pour cela. Il pourrait être intéressant d'utiliser un VIEW (et de la requête avec une clause where) à la place. Si ce n'est pas une bonne option, il y a la possibilité de retourner un TABLE à partir d'une procédure stockée dans la version 9.0.

0
répondu pyrocumulus 2011-03-28 22:11:13