Basisantwoord
Er zijn CTE's (Algemene tabeluitdrukkingen) in Postgres (zoals in elke grote moderne RDBMS behalve MySQL). Sinds versie 9.1 die CTE's voor het wijzigen van gegevens bevat. Die kunnen worden "genest".
Update:MySQL 8.0 voegt eindelijk CTE's toe.
In tegenstelling tot subquery's CTE's vormen een optimalisatiebarrière. De queryplanner kan geen triviale commando's in de hoofdcommando's opnemen of joins opnieuw ordenen tussen hoofdquery's en CTE's. Hetzelfde is mogelijk met subquery's. Kan (zeer) goed of (zeer) slecht zijn voor de prestaties, dat hangt ervan af.
Hoe dan ook, CTE's vereisen wat meer overhead (prestatiekosten) dan subquery's.
Update:Postgres 12 kan eindelijk gewone CTE's inline maken in de hoofdquery.
Details waar je niet om hebt gevraagd
Uw vraag is erg basic, het bovenstaande is waarschijnlijk voldoende om te beantwoorden. Maar ik zal een beetje toevoegen voor gevorderde gebruikers (en een codevoorbeeld om de syntaxis te tonen).
Alle CTE's van een zoekopdracht zijn gebaseerd op dezelfde momentopname van de databank. De volgende CTE kan de output opnieuw gebruiken van eerdere CTE's (interne tijdelijke tabellen), maar effecten op onderliggende tabellen zijn onzichtbaar voor andere CTE's. De volgorde van meerdere CTE's is willekeurig tenzij er wordt iets geretourneerd met de RETURNING
clausule voor INSERT
, UPDATE
, DELETE
- niet relevant voor SELECT
, omdat het niets verandert en gewoon leest van de momentopname.
Dat kan subtiele effecten hebben met meerdere updates die dezelfde rij zouden beïnvloeden. Slechts één update kan elke rij beïnvloeden. Welke wordt beïnvloed door de volgorde van CTE's.
Probeer de uitkomst te voorspellen:
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
Wees niet teleurgesteld, ik betwijfel of er hier velen zijn die het hadden kunnen doen. :)
De kern hiervan:vermijd tegenstrijdige opdrachten in CTE's.