Vous ne pouvez pas imbriquer INSERT
instructions dans un CASE
expression. D'après ce que je vois, cette approche complètement différente devrait le faire :
Hypothèses
-
Vous n'avez pas réellement besoin du
SELECT
externe . -
dm_name
/rm_name
sont définis uniques dansdm
/rm
et non vide (<> ''
). Vous devriez avoir unCHECK
contrainte pour s'en assurer. -
Colonne par défaut pour les deux
d_id
etr_id
enz
sont NULL (par défaut).
dm_name
et rm_name
mutuellement exclusif
Si les deux ne sont jamais présents en même temps.
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;
Le FULL JOIN .. ON FALSE
produit une table dérivée avec toutes les lignes de d1
et r1
ajouté avec NULL pour l'autre colonne respective (pas de chevauchement entre les deux). Nous avons donc juste besoin d'un INSERT
au lieu de deux. Optimisation mineure.
dm_name
et rm_name
peuvent coexister
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;
Remarques
Les deux versions fonctionnent également si aucune n'existe.
INSERT
n'insère rien si le SELECT
ne renvoie pas de ligne(s).
Si vous devez gérer un accès en écriture concurrent qui pourrait entrer en conflit avec cette opération, la solution rapide consisterait à verrouiller les tables impliquées avant d'exécuter cette instruction dans la même transaction.