Warum gibt es einen Unterschied im Verhalten zwischen der Verwendung einer Set Returning Function (SRF) in der SELECT-Liste und der Verwendung von SRF in der FROM-Klausel?
Zum Beispiel für eine einfache SRF, die 2 Zeilen zurückgibt:
CREATE OR REPLACE FUNCTION gen_series(out integer, out int)
RETURNS SETOF record AS $$
SELECT 1,1
UNION
SELECT 2,2;
$$ LANGUAGE SQL;
SELECT gen_series();
Gibt zwei einzelne Spaltenzeilen zurück, die jeweils einen Datensatz enthalten:
=> gen_series
------------
(1,1)
(2,2)
(2 rows)
Während SELECT * FROM gen_series();
zwei Zeilen mit erweitertem Datensatz zurückgegeben werden:
=> column1 | column2
---------+---------
1 | 1
2 | 2
(2 rows)
Wenn die SRF im Vergleich dazu eine einzelne Spalte zurückgibt, macht der Aufruf der SRF in der SELECT- oder FROM-Klausel keinen Unterschied. z.B:
=> SELECT generate_series(1,2);
generate_series
-----------------
1
2
(2 rows)
=> SELECT * FROM generate_series(1,2);
generate_series
-----------------
1
2
(2 rows)
Meine Fragen sind:
Ich verstehe nicht ganz, warum sich das SRF-Verhalten im zweiten Fall vom ersten Fall unterscheidet, nur weil die zurückgegebene Tabelle eine einzelne Spalte enthält. Ist das wirklich konsistentes Verhalten in Bezug auf Typen, Tupel und Mengen?
Was ist der Unterschied zwischen den beiden Fällen, der zu dem unterschiedlichen Verhalten führt?
SRF kann wie oben gezeigt als Tabellen verwendet werden, aber können Tabellen auch verwendet werden, um SRFs zu ersetzen? z.B
SELECT my_table;
Anscheinend ist dies nicht möglich, aber warum ist dies SELECT my_SRF();
möglich, wohingegen dies
SELECT my_table;
nicht zulässig ist (in Bezug auf Beziehungen und Mathematik)?
SELECT my_table;
ist keine gültige SyntaxAntworten:
Postgres behandelt den einfachen Fall anders. Mehrere Spalten werden als zusammengesetzter Typ (Tabellenzeile) behandelt, der nur zerlegt wird
SELECT * FROM ...
, während eine einzelne Spalte vom skalaren Typ als genau das behandelt wird, ohne dass ein zusammengesetzter Typ-Wrapper hinzugefügt wird. SoSELECT my_SRF()
ergibt sich das gleiche wieSELECT * FROM my_SRF()
für den einfachen Fall. Das Handbuch zu Tabellenfunktionen :Ich bin damit einverstanden, dass dies verwirrend ist, und Sie sind nicht die ersten, die verwirrt sind. (Betrachten Sie jedoch die Alternative: Das Hinzufügen eines zusammengesetzten Wrappers um eine einzelne Spalte kann noch verwirrender sein.)
Aber nicht so verwirrend wie das, was passiert, wenn Sie mehrere SRF-Funktionen in der
SELECT
Liste kombinieren . Dies wird sich mit Postgres 10 jedoch endgültig ändern:Der sichere und weniger verwirrende Weg für beide Fälle besteht darin, SRF-Funktionen in die
FROM
Klausel zu verschieben. Verwenden Sie einenLATERAL
Join, wenn Sie auf Spalten aus einer anderen Tabelle verweisen müssen. Das Handbuch schlägt vor:quelle