Deklarieren Sie eine Variable vom Tabellentyp in PL / pgSQL

8

Ich frage mich, ob es eine Möglichkeit gibt, eine Variable vom Typ table in PL / pgSQL zu deklarieren, um Abfrageergebnisse zu speichern. Wie kann ich zum Beispiel etwas ausdrücken wie:

q1 = select * from foo;
q2 = select * from bar;
for t1 in q1:
  for t2 in q2:
    -- do something with t1 and t2

Ich habe mir das Konstrukt return next angesehen, aber das scheint nur mit Rückgabewerten umgehen zu können.

JRR
quelle
2
PL / SQL => Oracle, PgPL / SQL => PostgreSQL. Mit welchem ​​arbeiten Sie?
Mat
@ Mat: Es ist übrigens PL / pgSQL .
Erwin Brandstetter

Antworten:

11

In PostgreSQL dient jeder Tabellenname automatisch als Typname für den Zeilentyp (auch als zusammengesetzter Typ bezeichnet ) - kein Tabellentyp, es gibt keine "Tabellentypen" oder "Tabellenvariablen" in Postgres ( aber es gibt typisierte Tabellen ).
Sie können also einfach eine Variable dieses Typs in deklarieren PL/pgSQL.

CREATE FUNCTION foo()
 RETURNS void LANGUAGE plpgsql AS
$func$
DECLARE
  q1 foo;  -- "foo" ...
  q2 bar;  -- ... and "bar" are existing (visible) table names
BEGIN

FOR q1 IN 
   SELECT * from foo
LOOP
   FOR q2 IN 
      SELECT * from bar
   LOOP
       -- do something with q1 and q2
       -- since q1 and q2 are well known types, you can access columns
       -- with attribute notation. Like: q1.col1
   END LOOP;
END LOOP;

END
$func$

Eine FORSchleife arbeitet mit einem eingebauten Cursor. Es gibt auch explizite Cursor in plpgsql.

Sie können auch einfach Variablen vom generischen Typ deklarieren record. Bei der Zuweisung kann automatisch jeder Zeilentyp verwendet werden. Es gelten jedoch besondere Regeln. Folgen Sie unbedingt dem Link und lesen Sie das Kapitel des Handbuchs!

Während es oft bequem ist, die Funktion zurückgeben zu lassen SETOF <table name>, ist die Rückgabe SETOF recordnicht so bequem. Das System weiß nicht, was die Funktion auf diese Weise zurückgibt, und Sie müssen bei jedem Aufruf eine Spaltendefinitionsliste hinzufügen. Welches ist ein Schmerz. Details zu Tabellenfunktionen im Handbuch .

Oft gibt es jedoch effizientere Lösungen mit einfachem SQL. Looping ist ein Maß für den letzten Ausweg, wenn Sie Dinge in einem Scan ausführen können, bei denen Sie mehrere Scans in reinem SQL benötigen würden.

Erwin Brandstetter
quelle
2
Beachten Sie auch, dass Sie, wenn Sie den Tabellentyp zurückgeben möchten, einfach etwas sagen können wieCREATE FUNCTION footest() RETURNS SETOF foo LANGUAGE PLPGSQL AS $$...
Chris Travers
Warum haben wir dann überhaupt die Funktion "zusammengesetzte Typen", wenn wir stattdessen Tabellen erstellen können, ohne Einschränkungen für zusammengesetzte Typen (keine Einschränkungen usw.)? Die einzige sinnvolle Möglichkeit, zusammengesetzte Typen zu verwenden, besteht darin, ein paar (oder mehrere) Parameter von einer Funktion zurückzugeben, anstatt dafür eine ganze Tabelle zu erstellen.
EngineerSpock