Grundlæggende svar
Der er CTE'er (Almindelige tabeludtryk) i Postgres (som i enhver større moderne RDBMS undtagen MySQL). Siden version 9.1 inkluderer det datamodificerende CTE'er. Disse kan "indlejres".
Opdatering:MySQL 8.0 tilføjer endelig CTE'er.
I modsætning til underforespørgsler CTE'er udgør optimeringsbarrierer. Forespørgselsplanlæggeren kan ikke indlejre trivielle kommandoer i hovedkommandoen eller omarrangere joinforbindelser mellem hovedforespørgsler og CTE'er. Det samme er muligt med underforespørgsler. Kan være (meget) god eller (meget) dårlig for ydeevnen, det afhænger af.
Uanset hvad kræver CTE'er lidt mere overhead (ydelsesomkostninger) end underforespørgsler.
Opdatering:Postgres 12 kan endelig inline almindelige CTE'er i hovedforespørgslen.
Detaljer, du ikke har bedt om
Dit spørgsmål er meget grundlæggende, ovenstående er nok nok til at besvare. Men jeg vil tilføje lidt for avancerede brugere (og et kodeeksempel for at vise syntaksen).
Alle CTE'er i en forespørgsel er baseret på det samme øjebliksbillede af databasen. Den næste CTE kan genbruge outputtet af tidligere CTE'er (interne midlertidige tabeller), men effekter på underliggende tabeller er usynlige for andre CTE'er. Sekvensen af flere CTE'er er vilkårlig medmindre noget returneres med RETURNING
klausul for INSERT
, UPDATE
, DELETE
- irrelevant for SELECT
, da den ikke ændrer noget og bare læser fra snapshottet.
Det kan have subtile effekter med flere opdateringer, der ville påvirke den samme række. Kun én opdatering kan påvirke hver række. Hvilken er påvirket af sekvensen af CTE'er.
Prøv at forudsige 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
Bliv ikke skuffet, jeg tvivler på, at der er mange her, der kunne have gjort det. :)
Kernen i dette:undgå modstridende kommandoer i CTE'er.