PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Allgemeine Abfrage als Spalte speichern?

Gibt es eine Möglichkeit, diese Unterauswahl als Pseudospalte in der Tabelle zu speichern?

Eine VIEW wie empfohlen wurde, ist eine vollkommen gültige Lösung. Mach es.

Aber es gibt einen anderen Weg, der Ihrer Frage noch besser entspricht. Sie können eine Funktion schreiben, die den Tabellentyp als Parameter zum emulieren nimmt ein "berechnetes Feld" oder "generierte Spalte" .

Betrachten Sie diesen Testfall, abgeleitet von Ihrer Beschreibung:

CREATE TABLE tbl_a (a_id int, col1 int, col2 int);
INSERT INTO tbl_a VALUES (1,1,1), (2,2,2), (3,3,3), (4,4,4);

CREATE TABLE tbl_b (b_id int, a_id int, colx int);
INSERT INTO tbl_b VALUES
  (1,1,5),  (2,1,5),  (3,1,1)
, (4,2,8),  (5,2,8),  (6,2,6)
, (7,3,11), (8,3,11), (9,3,11);

Erstellen Sie eine Funktion, die col3 emuliert :

CREATE FUNCTION col3(tbl_a)
  RETURNS int8
  LANGUAGE sql STABLE AS
$func$
SELECT sum(colx)
FROM   tbl_b b
WHERE  b.a_id = $1.a_id
$func$;

Jetzt können Sie Folgendes abfragen:

SELECT a_id, col1, col2, tbl_a.col3
FROM   tbl_a;

Oder sogar:

SELECT *, a.col3 FROM tbl_a a;

Beachten Sie, wie ich tbl_a.col3 geschrieben habe / a.col3 , nicht nur col3 . Dies ist wesentlich .

Im Gegensatz zu einer "virtuellen Spalte" in Oracle ist es nicht automatisch in einem SELECT * FROM tbl_a enthalten . Sie könnten eine VIEW verwenden dafür.

Warum funktioniert das?

Die übliche Art, auf eine Tabellenspalte zu verweisen, ist die Attributschreibweise :

SELECT tbl_a.col1 FROM tbl_a;

Die übliche Art, eine Funktion aufzurufen, ist die funktionale Notation :

SELECT col3(tbl_a);

Im Allgemeinen ist es am besten, sich an diese kanonischen Methoden zu halten , die dem SQL-Standard entsprechen.

Aber Postgres erlaubt auch die Notation von Attributen. Diese funktionieren auch:

SELECT col1(tbl_a) FROM tbl_a;
SELECT tbl_a.col3;

Mehr dazu im Handbuch.
Wahrscheinlich sehen Sie schon, wohin das führt. Das sieht aus als würden Sie eine zusätzliche Spalte der Tabelle tbl_a hinzufügen während col3() ist eigentlich eine Funktion, die die aktuelle Zeile von tbl_a übernimmt (oder sein Alias) als Zeilentypargument und berechnet einen Wert.

SELECT *, a.col3
FROM   tbl_a AS a;

Wenn es eine tatsächliche Spalte col3 gibt es hat Vorrang und das System sucht nicht nach einer Funktion dieses Namens, indem es die Zeile tbl_a verwendet als Parameter.

Das "Schöne" daran:Sie können Spalten von tbl_a hinzufügen oder löschen und die letzte Abfrage wird dynamisch alle aktuellen Spalten zurückgeben, während eine Ansicht nur solche Spalten zurückgeben würde, die zum Zeitpunkt der Erstellung vorhanden waren (frühe Bindung vs. späte Bindung von * ).
Natürlich müssen Sie die abhängige Funktion löschen, bevor Sie die Tabelle jetzt löschen können. Und Sie müssen aufpassen, dass Sie die Funktion nicht ungültig machen, wenn Sie Änderungen an der Tabelle vornehmen.

Ich würde es trotzdem nicht verwenden. Es ist zu überraschend für den unschuldigen Leser.