Nemůžete vnořit INSERT
příkazy v CASE
výraz. Podle toho, co vidím, by to měl udělat tento zcela odlišný přístup:
Předpoklady
-
Ve skutečnosti nepotřebujete vnější
SELECT
. -
dm_name
/rm_name
jsou definovány jako jedinečné vdm
/rm
a není prázdné (<> ''
). Měli byste mítCHECK
omezení, abyste se ujistili. -
Výchozí sloupec pro obě
d_id
ar_id
vz
jsou NULL (výchozí).
dm_name
a rm_name
vzájemně se vylučující
Pokud oba nejsou nikdy přítomny ve stejnou dobu.
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
vytvoří odvozenou tabulku se všemi řádky z d1
a r1
připojeno s NULL pro příslušný druhý sloupec (bez překrývání mezi těmito dvěma). Takže potřebujeme jen jeden INSERT
místo dvou. Drobná optimalizace.
dm_name
a rm_name
mohou koexistovat
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;
Poznámky
Obě verze také fungují, pokud žádná neexistuje.
INSERT
nevloží nic, pokud SELECT
nevrací řádek(y).
Pokud se musíte vypořádat se souběžným přístupem pro zápis, který by mohl být v konfliktu s touto operací, rychlým řešením by bylo uzamknout příslušné tabulky před spuštěním tohoto příkazu ve stejné transakci.