web-dev-qa-db-fra.com

Comment créer une fonction temporaire dans PostgreSQL?

Je dois exécuter une boucle dans la base de données. Ce n'est qu'une exigence unique. Après avoir exécuté la fonction, je laisse tomber la fonction maintenant.

Existe-t-il une bonne approche pour créer des fonctions temporaires/jetables?

60
Anand

J'avais besoin de savoir comment utiliser plusieurs fois dans un script que j'écrivais. Il s'avère que vous pouvez créer une fonction temporaire en utilisant le schéma pg_temp. Il s'agit d'un schéma créé à la demande pour votre connexion et où les tables temporaires sont stockées. Lorsque votre connexion est fermée ou expire, ce schéma est supprimé. Il s'avère que si vous créez une fonction sur ce schéma, le schéma sera créé automatiquement. Donc,

create function pg_temp.testfunc() returns text as 
$$ select 'hello'::text $$ language sql;

sera une fonction qui restera aussi longtemps que votre connexion restera. Pas besoin d'appeler une commande drop.

93
crowmagnumb

Quelques notes supplémentaires au astuce intelligente dans la réponse de @ crowmagnumb :

  • La fonction doit être qualifiée par le schéma à tout moment, même si pg_temp est dans le search_path (comme c'est par défaut), selon Tom Lane pour empêcher les chevaux de Troie:
CREATE FUNCTION pg_temp.f_inc(int)
  RETURNS int AS 'SELECT $1 + 1' LANGUAGE sql IMMUTABLE;

SELECT pg_temp.f_inc(42);
f_inc
-----
43
  • Une fonction créée dans le schéma temporaire n'est visible qu'à l'intérieur de la même session (tout comme les tables temporaires). Il est invisible pour toutes les autres sessions (même pour le même rôle). Vous pourriez accéder à la fonction en tant que rôle différent dans la même session après SET ROLE.

  • Vous pouvez même créer un index fonctionnel basé sur cette fonction "temp":

    CREATE INDEX foo_idx ON tbl (pg_temp.f_inc(id));
    

    De ce fait, la création d'un index simple à l'aide d'une fonction temporaire sur une table non temporaire. Un tel index serait visible pour toutes les sessions mais toujours valable uniquement pour la session de création. Le planificateur de requêtes n'utilisera pas d'index fonctionnel, où l'expression n'est pas répétée dans la requête. Encore un sale tour. Il sera supprimé automatiquement à la fermeture de la session - en tant qu'objet dépendant. Se sent comme ça ne devrait pas du tout être autorisé ...


Si vous avez juste besoin d'exécuter une fonction à plusieurs reprises et que vous n'avez besoin que de SQL, envisagez plutôt une instruction préparée . Il agit un peu comme une fonction SQL temporaire qui meurt à la fin de la session. Pas la chose même, cependant, et ne peut être utilisé que par lui-même avec EXECUTE, pas imbriqué dans une autre requête. Exemple:

PREPARE upd_tbl AS
UPDATE tbl t SET set_name = $2 WHERE tbl_id = $1;

Appel:

EXECUTE upd_tbl(123, 'foo_name');

Détails:

48
Erwin Brandstetter

Si vous utilisez la version 9.0, vous pouvez le faire avec la nouvelle instruction DO:

http://www.postgresql.org/docs/current/static/sql-do.html

Avec les versions précédentes, vous devrez créer la fonction, l'appeler et la supprimer à nouveau.

27
a_horse_with_no_name