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 idm
/rm
och inte tom (<> ''
). Du bör ha enCHECK
begränsning för att se till. -
Kolumn standard för båda
d_id
ochr_id
iz
ä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.