Non puoi annidare INSERT dichiarazioni in un CASE espressione. Derivato da quello che vedo, questo approccio completamente diverso dovrebbe farlo:
Ipotesi
-
In realtà non hai bisogno del
SELECTesterno . -
dm_name/rm_namesono definiti univoci indm/rme non vuoto (<> ''). Dovresti avere unCHECKvincolo per essere sicuro. -
Colonna predefinita per entrambi
d_ider_idinzsono NULL (predefinito).
dm_name e rm_name si escludono a vicenda
Se entrambi non sono mai presenti contemporaneamente.
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;
Il FULL JOIN .. ON FALSE produce una tabella derivata con tutte le righe da d1 e r1 aggiunto con NULL per la rispettiva altra colonna (nessuna sovrapposizione tra le due). Quindi abbiamo solo bisogno di un INSERT invece di due. Ottimizzazione minore.
dm_name e rm_name possono coesistere
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;
Note
Entrambe le versioni funzionano anche se nessuna delle due esiste.
INSERT non inserisce nulla se il SELECT non restituisce riga/i.
Se devi gestire un accesso in scrittura simultaneo che potrebbe entrare in conflitto con questa operazione, la soluzione rapida sarebbe bloccare le tabelle coinvolte prima di eseguire questa istruzione nella stessa transazione.