sql >> Database teknologi >  >> RDS >> PostgreSQL

Er SELECT-type-forespørgsler den eneste type, der kan indlejres?

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.




  1. Sådan indstilles samlingen af ​​en database i SQL Server (T-SQL)

  2. 7 gode tekniske vaner, som alle arbejdsgivere bør adoptere

  3. hvordan duplikere mine sql resultater?

  4. Oracle PL/SQL - Hvordan opretter man en simpel matrixvariabel?