sql >> Databasteknik >  >> RDS >> PostgreSQL

Är SELECT-frågor den enda typen som kan kapslas?

Grundläggande svar

Det finns CTE (Vanliga tabelluttryck) i Postgres (som i alla större moderna RDBMS förutom MySQL). Sedan version 9.1 inkluderar det datamodifierande CTE:er. De kan "kapslas".
Uppdatering:MySQL 8.0 lägger äntligen till CTE:er.

Till skillnad från underfrågor CTE utgör optimeringsbarriärer. Frågeplaneraren kan inte infoga triviala kommandon i huvudkommandot eller ordna om kopplingar mellan huvudfrågor och CTE:er. Detsamma är möjligt med underfrågor. Kan vara (mycket) bra eller (mycket) dåligt för prestanda, det beror på.
I vilket fall som helst kräver CTE:er lite mer overhead (prestandakostnad) än underfrågor.
Uppdatering:Postgres 12 kan äntligen infoga vanliga CTE:er i huvudfrågan.

Detaljer du inte har bett om

Din fråga är väldigt grundläggande, ovanstående är förmodligen tillräckligt för att besvara. Men jag ska lägga till lite för avancerade användare (och ett kodexempel för att visa syntaxen).

Alla CTE i en fråga är baserade på samma ögonblicksbild av databasen. Nästa CTE kan återanvända utgången av tidigare CTE (interna temporära tabeller), men effekter på underliggande tabeller är osynliga för andra CTE. Sekvensen av flera CTE:er är godtycklig om inte något returneras med RETURNING sats för INSERT , UPDATE , DELETE - irrelevant för SELECT , eftersom det inte ändrar någonting och bara läser från ögonblicksbilden.

Det kan ha subtila effekter med flera uppdateringar som skulle påverka samma rad. Endast en uppdatering kan påverka varje rad. Vilken som påverkas av sekvensen av CTE.

Försök att förutsäga resultatet:

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 Fiddle

Bli inte besviken, jag tvivlar på att det finns många här som kunde ha gjort det. :)
Synen av detta:undvik motstridiga kommandon i CTE.




  1. Anslut till SQL Server med Windows-autentisering från en Linux-maskin via JDBC

  2. Hur man skapar länkad server MySQL

  3. Anropa en lagrad procedur med en annan i Oracle

  4. Fel 1022 - Kan inte skriva; dubblettnyckel i tabellen