Return SETOF Datensatz (virtuelle Tabelle) aus der Funktion
-
11-09-2019 - |
Frage
Ich brauche eine Postgres-Funktion eine virtuelle Tabelle zurückzukehren (wie in Oracle) mit benutzerdefinierten Inhalt. Die Tabelle würde 3 Spalten und eine unbekannte Anzahl von Zeilen.
Ich konnte einfach nicht die richtige Syntax im Internet finden.
Stell dir vor:
CREATE OR REPLACE FUNCTION "public"."storeopeninghours_tostring" (numeric)
RETURNS setof record AS
DECLARE
open_id ALIAS FOR $1;
returnrecords setof record;
BEGIN
insert into returnrecords('1', '2', '3');
insert into returnrecords('3', '4', '5');
insert into returnrecords('3', '4', '5');
RETURN returnrecords;
END;
Wie das richtig geschrieben?
Lösung
(Dies alles mit postgresql getestet 8.3.7-- Sie haben eine frühere Version? Nur bei der Nutzung von „ALIAS für $ 1“ suchen)
CREATE OR REPLACE FUNCTION storeopeninghours_tostring(numeric)
RETURNS SETOF RECORD AS $$
DECLARE
open_id ALIAS FOR $1;
result RECORD;
BEGIN
RETURN QUERY SELECT '1', '2', '3';
RETURN QUERY SELECT '3', '4', '5';
RETURN QUERY SELECT '3', '4', '5';
END
$$;
Wenn Sie einen Datensatz oder Zeile Variable zurück (anstelle eines Abfrageergebnis), verwenden Sie "NEXT RETURN" und nicht als "RETURN QUERY".
Um die Funktion Sie etwas tun müssen, aufrufen:
select * from storeopeninghours_tostring(1) f(a text, b text, c text);
Sie haben also zu definieren, was Sie die Ausgabezeile Schema der Funktion erwarten in der Abfrage sein. Um zu vermeiden, dass können Sie Ausgangsgrößen in der Funktionsdefinition angegeben werden:
CREATE OR REPLACE FUNCTION storeopeninghours_tostring(open_id numeric, a OUT text, b OUT text, c OUT text)
RETURNS SETOF RECORD LANGUAGE 'plpgsql' STABLE STRICT AS $$
BEGIN
RETURN QUERY SELECT '1'::text, '2'::text, '3'::text;
RETURN QUERY SELECT '3'::text, '4'::text, '5'::text;
RETURN QUERY SELECT '3'::text, '4'::text, '5'::text;
END
$$;
(nicht ganz sicher, warum die zusätzliche :: Text Abgüsse erforderlich ist ... '1' ist ein varchar standardmäßig vielleicht?)
Andere Tipps
Alle bisher vorhandenen Antworten sind veraltet oder ineffizient zu beginnen.
Angenommen, Sie drei integer
Spalten zurückgeben möchten.
PL / pgSQL Funktion
Hier ist, wie Sie es tun mit modernen PL / pgSQL (PostgreSQL 8.4 oder höher):
CREATE OR REPLACE FUNCTION f_foo() -- (open_id numeric) -- parameter not used
RETURNS TABLE (a int, b int, c int) AS
$func$
BEGIN
RETURN QUERY VALUES
(1,2,3)
, (3,4,5)
, (3,4,5)
;
END
$func$ LANGUAGE plpgsql IMMUTABLE ROWS 3;
In Postgres 9.6 oder später können Sie auch hinzufügen PARALLEL SAFE
.
Call:
SELECT * FROM f_foo();
Wichtige Punkte
-
Verwenden Sie
RETURNS TABLE
zu definieren, eine Ad-hoc Zeilentyp zurückzukehren.
OderRETURNS SETOF mytbl
eine vordefinierte Zeilentyp zu verwenden. -
Verwenden Sie
RETURN QUERY
zurückzukehren mehrere Zeilen mit einem Befehl. -
Verwenden Sie einen
VALUES
Ausdruck mehrere Zeilen eingeben manuell. Dies ist Standard-SQL und hat rund immer . -
Wenn Sie tatsächlich einen Parameter benötigen, einen Parameternamen
(open_id numeric)
anstelle vonALIAS
, die abgeraten. Im Beispiel wurde der Parameter nicht verwendet und nur Rauschen ... -
Keine Notwendigkeit für Doppel zitierte vollkommen legal Identifikatoren. Doppelte Anführungszeichen sind nur zu zwingen, sonst illegal Namen erforderlich (Groß- und Kleinschreibung, ungültige Zeichen oder reservierte Worte).
-
Funktion Volatilität kann
IMMUTABLE
werden, da das Ergebnis ändert sich nie. -
ROWS 3
ist optional, aber da wir wissen , wie viele Zeilen zurückgegeben werden, können wir auch, es zu Postgres erklären. Kann die Abfrage Planern helfen, den besten Plan zu wählen.
Einfache SQL
Für einen einfachen Fall wie diesen, können Sie eine einfache SQL-Anweisung verwenden, statt:
VALUES (1,2,3), (3,4,5), (3,4,5)
Oder, wenn Sie wollen (oder müssen) bestimmte Spaltennamen und -typen definieren:
SELECT *
FROM (
VALUES (1::int, 2::int, 3::int)
, (3, 4, 5)
, (3, 4, 5)
) AS t(a, b, c);
SQL-Funktion
Sie können es in eine einfache SQL-Funktion rel="nofollow statt:
CREATE OR REPLACE FUNCTION f_foo()
RETURNS TABLE (a int, b int, c int) AS
$func$
VALUES (1, 2, 3)
, (3, 4, 5)
, (3, 4, 5);
$func$ LANGUAGE sql IMMUTABLE ROWS 3;
Ich benutze temporäre Tabellen ziemlich viel in meinen Funktionen. Sie benötigen einen Rückgabetyp auf der Datenbank erstellen und dann eine Variable dieses Typs zurück erstellen. Im Folgenden finden Sie Beispielcode, der genau das tut.
CREATE TYPE storeopeninghours_tostring_rs AS
(colone text,
coltwo text,
colthree text
);
CREATE OR REPLACE FUNCTION "public"."storeopeninghours_tostring" () RETURNS setof storeopeninghours_tostring_rs AS
$BODY$
DECLARE
returnrec storeopeninghours_tostring_rs;
BEGIN
BEGIN
CREATE TEMPORARY TABLE tmpopeninghours (
colone text,
coltwo text,
colthree text
);
EXCEPTION WHEN OTHERS THEN
TRUNCATE TABLE tmpopeninghours; -- TRUNCATE if the table already exists within the session.
END;
insert into tmpopeninghours VALUES ('1', '2', '3');
insert into tmpopeninghours VALUES ('3', '4', '5');
insert into tmpopeninghours VALUES ('3', '4', '5');
FOR returnrec IN SELECT * FROM tmpopeninghours LOOP
RETURN NEXT returnrec;
END LOOP;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
select * from storeopeninghours_tostring()
Für diejenigen, die hier gelandet sind, die Suche nach dem MSSQL äquivalent eine temporäre Tabelle erstellen und seine Aufzeichnungen als Rückkehr Dumping aus ..., die nicht in PostgreSQL :( existiert -. Sie den Rückgabetyp definieren müssen Es gibt zwei Wege zum Zeitpunkt der Funktion Schöpfung dies zu tun, oder zum Zeitpunkt der Erstellung der Abfrage.
Siehe hier: http://wiki.postgresql.org/wiki/Return_more_than_one_row_of_data_from_PL/pgSQL_functions
CREATE OR REPLACE FUNCTION foo(open_id numeric, OUT p1 varchar, OUT p2 varchar, OUT p3 varchar) RETURNS SETOF RECORD AS $$
BEGIN
p1 := '1'; p2 := '2'; p3 := '3';
RETURN NEXT;
p1 := '3'; p2 := '4'; p3 := '5';
RETURN NEXT;
p1 := '3'; p2 := '4'; p3 := '5';
RETURN NEXT;
RETURN;
END;
$$ LANGUAGE plpgsql;