Grundlegendes zur Set Returning Function (SRF) in der SELECT-Liste


8

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:

  1. 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?

  2. Was ist der Unterschied zwischen den beiden Fällen, der zu dem unterschiedlichen Verhalten führt?

  3. 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 Syntax
Mladen Uzelac

Antworten:


3

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. So SELECT my_SRF()ergibt sich das gleiche wie SELECT * FROM my_SRF()für den einfachen Fall. Das Handbuch zu Tabellenfunktionen :

Tabellenfunktionen sind Funktionen, die eine Reihe von Zeilen erzeugen, die entweder aus Basisdatentypen (Skalartypen) oder zusammengesetzten Datentypen (Tabellenzeilen) bestehen.

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 SELECTListe 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 FROMKlausel zu verschieben. Verwenden Sie einen LATERALJoin, wenn Sie auf Spalten aus einer anderen Tabelle verweisen müssen. Das Handbuch schlägt vor:

Die LATERALSyntax führt beim Aufrufen mehrerer Set-Return-Funktionen zu weniger überraschenden Ergebnissen und sollte normalerweise stattdessen verwendet werden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.