Не можете да вложите INSERT
изрази в CASE
изразяване. Излизайки от това, което виждам, този напълно различен подход би трябвало да го направи:
Предположения
-
Всъщност не се нуждаете от външния
SELECT
. -
dm_name
/rm_name
са дефинирани уникални вdm
/rm
и не е празен (<> ''
). Трябва да иматеCHECK
ограничение, за да се уверите. -
Колоната по подразбиране и за двата
d_id
иr_id
вz
са NULL (по подразбиране).
dm_name
и rm_name
взаимно изключващи се
Ако и двете никога не присъстват едновременно.
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
произвежда извлечена таблица с всички редове от d1
и r1
добавен с NULL за съответната друга колона (без припокриване между двете). Така че имаме нужда само от един INSERT
вместо две. Незначителна оптимизация.
dm_name
и rm_name
може да съществува едновременно
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;
Бележки
И двете версии също работят, ако нито една не съществува.
INSERT
не вмъква нищо, ако SELECT
не връща ред(ове).
Ако трябва да се справите с едновременен достъп за запис, който може да е в конфликт с тази операция, бързото решение би било да заключите включени таблици, преди да изпълните този израз в същата транзакция.