sql >> Databáze >  >> RDS >> PostgreSQL

Kombinace příkazů INSERT v CTE modifikující data s výrazem CASE

Nemůžete vnořit INSERT příkazy v CASE výraz. Podle toho, co vidím, by to měl udělat tento zcela odlišný přístup:

Předpoklady

  • Ve skutečnosti nepotřebujete vnější SELECT .

  • dm_name / rm_name jsou definovány jako jedinečné v dm / rm a není prázdné (<> '' ). Měli byste mít CHECK omezení, abyste se ujistili.

  • Výchozí sloupec pro obě d_id a r_id v z jsou NULL (výchozí).

dm_name a rm_name vzájemně se vylučující

Pokud oba nejsou nikdy přítomny ve stejnou dobu.

WITH d1 AS (
   INSERT INTO d (dm_id)
   SELECT dm.dm_id 
   FROM   import
   JOIN   dm USING (dm_name)
   RETURNING d_id
   )
, r1 AS (
   INSERT INTO r (rm_id)
   SELECT rm.rm_id 
   FROM   import
   JOIN   rm USING (rm_name)
   RETURNING r_id
   )
, z1 AS (
   INSERT INTO z (d_id, r_id)
   SELECT d_id, r_id
   FROM d1 FULL JOIN r1 ON FALSE
   RETURNING z_id
   )
INSERT INTO port (z_id)
SELECT z_id
FROM   z1;

FULL JOIN .. ON FALSE vytvoří odvozenou tabulku se všemi řádky z d1 a r1 připojeno s NULL pro příslušný druhý sloupec (bez překrývání mezi těmito dvěma). Takže potřebujeme jen jeden INSERT místo dvou. Drobná optimalizace.

dm_name a rm_name mohou koexistovat

WITH i AS (
   SELECT dm.dm_id, rm.rm_id
   FROM   import
   LEFT   JOIN dm USING (dm_name)
   LEFT   JOIN rm USING (rm_name)
   )
, d1 AS (
   INSERT INTO d (dm_id)
   SELECT dm_id FROM i WHERE dm_id IS NOT NULL
   RETURNING dm_id, d_id
   )
, r1 AS (
   INSERT INTO r (rm_id)
   SELECT rm_id FROM i WHERE rm_id IS NOT NULL
   RETURNING rm_id, r_id
   )
, z1 AS (
   INSERT INTO z (d_id, r_id)
   SELECT d1.d_id, r1.r_id
   FROM   i
   LEFT   JOIN d1 USING (dm_id)
   LEFT   JOIN r1 USING (rm_id)
   WHERE  d1.dm_id IS NOT NULL OR
          r1.rm_id IS NOT NULL
   RETURNING z_id
   )
INSERT INTO port (z_id)
SELECT z_id FROM z1;

Poznámky

Obě verze také fungují, pokud žádná neexistuje.

INSERT nevloží nic, pokud SELECT nevrací řádek(y).

Pokud se musíte vypořádat se souběžným přístupem pro zápis, který by mohl být v konfliktu s touto operací, rychlým řešením by bylo uzamknout příslušné tabulky před spuštěním tohoto příkazu ve stejné transakci.




  1. Jak rozdělím řetězec, abych měl přístup k položce x?

  2. Operátor SQL se rovná (=) pro začátečníky

  3. stránkování v zobrazení seznamu

  4. Jak nainstalovat SQL Server na Windows