Wie erstelle ich eine temporäre Funktion in PostgreSQL?

80

Ich muss eine Schleife in der Datenbank ausführen. Dies ist nur eine einmalige Anforderung. Nach dem Ausführen der Funktion lösche ich die Funktion jetzt.

Gibt es einen guten Ansatz für die Erstellung temporärer / verfügbarer Funktionen?

Anand
quelle

Antworten:

113

Ich musste wissen, wie man ein Skript, das ich schrieb, oft verwendet. Es stellt sich heraus, dass Sie mithilfe des Schemas pg_temp eine temporäre Funktion erstellen können. Dies ist ein Schema, das bei Bedarf für Ihre Verbindung erstellt wird und in dem temporäre Tabellen gespeichert werden. Wenn Ihre Verbindung geschlossen wird oder abläuft, wird dieses Schema gelöscht. Wenn Sie eine Funktion für dieses Schema erstellen, wird das Schema automatisch erstellt. Deshalb,

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

wird eine Funktion sein, die so lange bestehen bleibt, wie Ihre Verbindung bestehen bleibt. Sie müssen keinen Drop-Befehl aufrufen.

Crowmagnumb
quelle
60

Ein paar zusätzliche Anmerkungen zum intelligenten Trick in der Antwort von @ crowmagnumb :

  • Die Funktion muss laut Tom Lane jederzeit schemaqualifiziert sein, auch wenn sie pg_tempsich in der search_path(wie standardmäßig) befindet, um Trojaner zu verhindern:
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
  • Eine im temporären Schema erstellte Funktion ist nur innerhalb derselben Sitzung sichtbar (genau wie temporäre Tabellen). Es ist für alle anderen Sitzungen unsichtbar (auch für dieselbe Rolle). Sie können danach in derselben Sitzung als andere Rolle auf die Funktion zugreifen SET ROLE.

  • Sie können sogar einen Funktionsindex erstellen, der auf dieser "temporären" Funktion basiert:

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

    Dadurch wird ein einfacher Index mit einer temporären Funktion für eine nicht temporäre Tabelle erstellt. Ein solcher Index wäre für alle Sitzungen sichtbar, aber nur für die Erstellungssitzung gültig. Der Abfrageplaner verwendet keinen Funktionsindex, bei dem der Ausdruck in der Abfrage nicht wiederholt wird. Immer noch ein schmutziger Trick. Es wird automatisch gelöscht, wenn die Sitzung geschlossen wird - als abhängiges Objekt. Gefühle wie diese sollten überhaupt nicht erlaubt sein ...


Wenn Sie eine Funktion nur wiederholt ausführen müssen und nur SQL benötigen, ziehen Sie stattdessen eine vorbereitete Anweisung in Betracht . Es verhält sich ähnlich wie eine temporäre SQL-Funktion , die am Ende der Sitzung stirbt. Dies ist jedoch nicht dasselbe und kann nur für sich allein verwendet werden EXECUTE, nicht in einer anderen Abfrage verschachtelt. Beispiel:

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

Anruf:

EXECUTE upd_tbl(123, 'foo_name');

Einzelheiten:

Erwin Brandstetter
quelle
30

Wenn Sie Version 9.0 verwenden, können Sie dies mit der neuen DO-Anweisung tun:

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

In früheren Versionen müssen Sie die Funktion erstellen, aufrufen und erneut löschen.

ein Pferd ohne Name
quelle
4
... Es ist nützlich für Skripte auf dem Terminal, aber Sie können es nicht erneut aufrufen, wie eine "anonyme Funktion" (oder Lambda), daher ist die DO-Anweisung nicht so nützlich wie eine "temporäre Funktion".
Peter Krauss
@PeterKrauss: Wenn Sie es erneut aufrufen möchten, müssen Sie eine echte Funktion erstellen.
a_horse_with_no_name
Natürlich meine a_hourse :-) Ich habe nur den theoretischen Pfad für die Implementierung "temporär" gezeigt ... Deshalb ist die bessere Antwort (möglich mit PostgreSQL) für die Hauptfrage pg_temp.foo(). Ich verstehe nicht, warum (!?) Heute, 2014, mit so einfachen und so schnellen Beispielen wie Lua , SQL DML- Sprachen keine Lambda-Funktionen (!) Bieten können .
Peter Krauss
7
Außerdem können DOAnweisungen keine Eingabeparameter haben und im Gegensatz zu Funktionen kein Ergebnis zurückgeben.
Daniel Vérité
2
Wenn es nicht zurückkehrt, sollten wir es eine "Funktion" nennen?
AndreKR
-4

Für Ad-Hock-Verfahren sind Cursor nicht schlecht. Sie sind jedoch für den Produktgebrauch zu ineffizient.

Mit ihnen können Sie problemlos SQL-Ergebnisse in der Datenbank durchlaufen.

Byron Whitlock
quelle
6
Warum sind Cursor Ihrer Meinung nach in PostgreSQL ineffizient?
Frank Heikens
2
Cursor halten eine Datenbankverbindung in der Schleife aufrecht. Eine Webseite mit Hunderten von lang laufenden Cursorn wird Verbindungen aushungern lassen und die Site / Datenbank in die Knie zwingen.
Byron Whitlock