sql >> Databasteknik >  >> RDS >> PostgreSQL

Kombinera INSERT-satser i en datamodifierande CTE med ett CASE-uttryck

Du kan inte kapsla INSERT uttalanden i en CASE uttryck. Enligt vad jag ser borde detta helt annorlunda tillvägagångssätt göra det:

Antaganden

  • Du behöver faktiskt inte den yttre SELECT .

  • dm_name / rm_name definieras unika i dm / rm och inte tom (<> '' ). Du bör ha en CHECK begränsning för att se till.

  • Kolumn standard för båda d_id och r_id i z är NULL (standard).

dm_name och rm_name ömsesidigt utesluter

Om båda aldrig är närvarande samtidigt.

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 producerar en härledd tabell med alla rader från d1 och r1 läggs till med NULL för respektive andra kolumn (ingen överlappning mellan de två). Så vi behöver bara en INSERT istället för två. Mindre optimering.

dm_name och rm_name kan samexistera

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;

Anteckningar

Båda versionerna fungerar också om ingen av dem finns.

INSERT infogar ingenting om SELECT returnerar inte rad(er).

Om du måste hantera samtidig skrivåtkomst som kan komma i konflikt med den här operationen skulle snabblösningen vara att låsa inblandade tabeller innan du kör den här satsen i samma transaktion.




  1. SQL Server PIVOT kanske?

  2. Kan vi ansluta fjärransluten MySQL-databas i Android med JDBC?

  3. MySQL UPPDATERING och SELECT i ett pass

  4. Stöder SQLDeveloper exekvering av skript?