Du kan ikke indlejre INSERT
udsagn i en CASE
udtryk. Ud fra hvad jeg ser, burde denne helt anderledes tilgang gøre det:
Forudsætninger
-
Du behøver faktisk ikke den ydre
SELECT
. -
dm_name
/rm_name
er defineret unikke idm
/rm
og ikke tom (<> ''
). Du skal have enCHECK
begrænsning for at sikre. -
Kolonnestandard for både
d_id
ogr_id
iz
er NULL (standard).
dm_name
og rm_name
gensidigt udelukker
Hvis begge aldrig er til stede på samme tid.
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
producerer en afledt tabel med alle rækker fra d1
og r1
tilføjet NULL for den respektive anden kolonne (ingen overlap mellem de to). Så vi mangler bare én INSERT
i stedet for to. Mindre optimering.
dm_name
og rm_name
kan sameksistere
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;
Bemærkninger
Begge versioner fungerer også, hvis ingen af dem findes.
INSERT
indsætter intet, hvis SELECT
returnerer ikke række(r).
Hvis du skal håndtere samtidig skriveadgang, der kan være i konflikt med denne handling, ville den hurtige løsning være at låse involverede tabeller, før du kører denne sætning i samme transaktion.