U kunt INSERT
niet nesten uitspraken in een CASE
uitdrukking. Afgeleid van wat ik zie, zou deze totaal andere benadering het moeten doen:
Aannames
-
Je hebt de buitenste
SELECT
eigenlijk niet nodig . -
dm_name
/rm_name
zijn uniek gedefinieerd indm
/rm
en niet leeg (<> ''
). U moet eenCHECK
. hebben beperking om zeker te zijn. -
Kolomstandaard voor beide
d_id
enr_id
inz
zijn NULL (standaard).
dm_name
en rm_name
elkaar uitsluiten
Als beide nooit tegelijkertijd aanwezig zijn.
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;
De FULL JOIN .. ON FALSE
produceert een afgeleide tabel met alle rijen van d1
en r1
toegevoegd met NULL voor de respectieve andere kolom (geen overlap tussen de twee). Dus we hebben er maar één nodig INSERT
in plaats van twee. Kleine optimalisatie.
dm_name
en rm_name
kunnen naast elkaar bestaan
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;
Opmerkingen
Beide versies werken ook als geen van beide bestaat.
INSERT
voegt niets in als de SELECT
retourneert geen rij(en).
Als u te maken krijgt met gelijktijdige schrijftoegang die in strijd zou kunnen zijn met deze bewerking, is de snelle oplossing om de betrokken tabellen te vergrendelen voordat u deze instructie in dezelfde transactie uitvoert.