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
SELECT
esterno . -
dm_name
/rm_name
sono definiti univoci indm
/rm
e non vuoto (<> ''
). Dovresti avere unCHECK
vincolo per essere sicuro. -
Colonna predefinita per entrambi
d_id
er_id
inz
sono 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.