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

Sind Abfragen vom Typ SELECT der einzige Typ, der verschachtelt werden kann?

Grundlegende Antwort

Es gibt CTEs (Allgemeine Tabellenausdrücke) in Postgres (wie in jedem großen modernen RDBMS außer MySQL). Seit Version 9.1 enthält dies datenmodifizierende CTEs. Diese können "verschachtelt" werden.
Update:MySQL 8.0 fügt endlich CTEs hinzu.

Im Gegensatz zu Unterabfragen CTEs stellen Optimierungsbarrieren dar. Der Abfrageplaner kann keine trivialen Befehle in den Hauptbefehl einfügen oder Verknüpfungen zwischen Hauptabfrage und CTEs neu anordnen. Dasselbe ist mit Unterabfragen möglich. Kann (sehr) gut oder (sehr) schlecht für die Leistung sein, das hängt davon ab.
In jedem Fall erfordern CTEs etwas mehr Overhead (Leistungskosten) als Unterabfragen.
Update:Postgres 12 kann endlich einfache CTEs inline in der Hauptabfrage.

Details, nach denen Sie nicht gefragt haben

Ihre Frage ist sehr einfach, das obige reicht wahrscheinlich aus, um sie zu beantworten. Aber ich werde etwas für fortgeschrittene Benutzer hinzufügen (und ein Codebeispiel, um die Syntax zu zeigen).

Alle CTEs einer Abfrage basieren auf derselben Momentaufnahme der Datenbank. Der nächste CTE kann die Ausgabe wiederverwenden von vorherigen CTEs (interne temporäre Tabellen), aber Auswirkungen auf zugrunde liegende Tabellen sind für andere CTEs unsichtbar. Die Reihenfolge mehrerer CTEs ist willkürlich es sei denn mit dem RETURNING wird etwas zurückgegeben -Klausel für INSERT , UPDATE , DELETE - irrelevant für SELECT , da es nichts ändert und nur aus dem Snapshot liest.

Das kann bei mehreren Aktualisierungen, die dieselbe Zeile betreffen würden, subtile Auswirkungen haben. Nur eine update kann sich auf jede Zeile auswirken. Welche wird durch die Folge der CTEs beeinflusst.

Versuchen Sie, das Ergebnis vorherzusagen:

CREATE TEMP TABLE t (t_id int, txt text);
INSERT INTO t VALUES (1, 'foo'), (2, 'bar'), (3, 'baz');

WITH sel AS (SELECT * FROM t)
   , up1 AS (UPDATE t SET txt = txt || '1' WHERE t_id = 1 RETURNING *)
   , up2 AS (UPDATE t SET txt = t.txt || '2'
             FROM   up1
             WHERE  up1.t_id = t.t_id
             RETURNING t.*)
   , ins AS (INSERT INTO t VALUES (4, 'bamm'))
   , up3 AS (UPDATE t SET txt = txt || '3' RETURNING *)
SELECT 'sel' AS source, * FROM sel
UNION ALL
SELECT 'up1' AS source, * FROM up1
UNION ALL
SELECT 'up2' AS source, * FROM up2
UNION ALL
SELECT 'up3' AS source, * FROM up3
UNION ALL
SELECT 't'   AS source, * FROM t;

SQL-Geige

Seien Sie nicht enttäuscht, ich bezweifle, dass es hier viele gibt, die das hätten tun können. :)
Das Wesentliche:vermeiden widersprüchliche Befehle in CTEs.