No puede anidar INSERT
declaraciones en un CASE
expresión. Derivando de lo que veo, este enfoque completamente diferente debería hacerlo:
Supuestos
-
En realidad no necesitas el
SELECT
externo . -
dm_name
/rm_name
se definen como únicos endm
/rm
y no vacío (<> ''
). Deberías tener unCHECK
restricción para asegurarse. -
Columna predeterminada para ambos
d_id
yr_id
enz
son NULL (predeterminados).
dm_name
y rm_name
mutuamente excluyentes
Si ambos nunca están presentes al mismo tiempo.
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
produce una tabla derivada con todas las filas desde d1
y r1
adjunto con NULL para la otra columna respectiva (sin superposición entre los dos). Así que solo necesitamos un INSERT
en lugar de dos. Optimización menor.
dm_name
y rm_name
pueden coexistir
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;
Notas
Ambas versiones también funcionan si ninguna existe.
INSERT
no inserta nada si SELECT
no devuelve fila(s).
Si tiene que lidiar con el acceso de escritura simultáneo que podría entrar en conflicto con esta operación, la solución rápida sería bloquear las tablas involucradas antes de ejecutar esta instrucción en la misma transacción.