2017-09-11 4 views
1

J'ai une partie d'une instruction SELECT qui est un ensemble assez long d'instructions conditionnelles. Je veux le mettre dans une fonction afin que je puisse l'appeler beaucoup plus efficacement sur n'importe quelle table dont j'ai besoin pour l'utiliser.Comment placer une partie d'une instruction SELECT dans une fonction Postgres

Ainsi, au lieu de:

SELECT 
    itemnumber, 
    itemname, 
    base, 
    CASE 
     WHEN labor < 100 AND overhead < .20 THEN 
     WHEN ..... 
     WHEN ..... 
     WHEN ..... 
     ..... 
    END AS add_cost, 
    gpm 
FROM items1; 

je peux faire:

SELECT 
    itemnumber, 
    itemname, 
    base, 
    calc_add_cost(), 
    gpm 
FROM items1; 

Est-il possible d'ajouter une partie d'un SELECT à une fonction de sorte que puisse être injecté juste en appelant la fonction?

Je suis en train de trier la documentation et Google, et il semble qu'il pourrait être possible de créer la fonction dans le langage plpgsql par opposition à sql. Cependant, ce que je lis n'est pas très clair.

+0

Vous avez besoin d'une procédure stockée pour la déclaration de cas. Il suffit de google et votre problème sera résolu. –

+2

@AnkitBajpai: Il n'y a pas de véritables "procédures stockées" dans Postgres. Juste des fonctions, faire presque mais pas tout à fait la même chose. (Et tout ce dont nous avons besoin ici est une fonction.) –

+0

BTW, vous venez de fermer votre question connexe (https://stackoverflow.com/questions/46164931/pass-the-table-name-used-in-from-to-function -automatically-in-postgresql-9-6-3) - il y a * un * moyen d'utiliser les types de tables de variables en entrée - et de faire ressembler cela à une colonne générée. Si vous en avez toujours besoin, rouvrez cette autre question. –

Répondre

2

Vous ne pouvez pas simplement insérer une partie d'une instruction SELECT dans une fonction. Mais une expression comme votre CASE peut facilement être enveloppé:

CREATE OR REPLACE FUNCTION pg_temp.calc_add_cost(_labor integer, _overhead numeric) 
    RETURNS numeric AS 
$func$ 
SELECT 
    CASE 
     WHEN _labor < 100 AND _overhead < .20 THEN numeric '1' -- example value 
--  WHEN ..... 
--  WHEN ..... 
--  WHEN ..... 
     ELSE numeric '0' -- example value 
    END; 
$func$ 
    LANGUAGE sql IMMUTABLE; 

Pendant que vous pourrait également utiliser PL/pgSQL pour cela, la démo est une simple fonction SQL. Voir:

Adapt types d'entrée et de données de sortie à votre besoin. Juste deviner integer et numeric par manque d'information.

Appel:

SELECT calc_add_cost(1, 0.1); 

Dans votre déclaration:

SELECT 
    itemnumber, 
    itemname, 
    base, 
    calc_add_cost(labor, overhead) AS add_cost, -- pass column values as input 
    gpm 
FROM items1; 

Vous devez comprendre quelques notions de base sur les fonctions Postgres pour faire un bon usage. Pourrait commencer avec la page de manuel sur CREATE FUNCTION.

Il ya aussi beaucoup questions connexes & réponses ici sur SO.

Voir aussi l'affaire connexe, plus sophistiqué en passant des lignes entières ici:

+0

Et s'il a besoin d'un tas de colonnes de la table. Comment passeriez-vous la rangée entière à la fonction? – Andreas

+2

@Andreas: Vous pouvez passer une ligne entière. La syntaxe serait 'SELECT calc_add_cost (t) FROM mytable t;' Voir: https://stackoverflow.com/questions/31148157/how-do-i-pass-in-a-table-parameter-to-this-function/ 31167928 # 31167928 Mais puisque l'OP veut utiliser la fonction 'sur n'importe quelle table je dois l'utiliser dessus, il serait imprudent de lier la fonction à un type de ligne particulier en entrée. Il y a aussi des types composites. Tout est possible, cela dépend du cas d'utilisation exact. –

+0

Salut, merci! Cela m'a beaucoup aidé à démarrer et m'a aidé à répondre à une autre question que j'avais posée aujourd'hui. En ce qui concerne le passage d'une ligne entière, cette table a environ 50 colonnes dont peut-être 8 seront passées dans cette fonction. À quel point est-il sensé de passer toute la rangée? Et aussi, il semble que si je passe toute la ligne, je n'ai pas besoin de spécifier les colonnes à passer dans la fonction comme arguments, mais je peux spécifier ces colonnes à l'intérieur de la fonction? En d'autres termes, passer la ligne me donne accès aux colonnes sans les spécifier lors de l'appel de la fonction? – sockpuppet