Você não pode aninhar
INSERT
instruções em um CASE
expressão. Derivando do que vejo, essa abordagem completamente diferente deve fazê-lo:Suposições
-
Na verdade, você não precisa doSELECT
externo .
-
dm_name
/rm_name
são definidos como únicos emdm
/rm
e não vazio (<> ''
). Você deve ter umCHECK
restrição para ter certeza.
-
Coluna padrão para ambosd_id
er_id
emz
são NULL (padrão).
dm_name
e rm_name
mutuamente exclusivos
Se ambos nunca estiverem presentes ao mesmo tempo.
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;
O
FULL JOIN .. ON FALSE
produz uma tabela derivada com todas as linhas de d1
e r1
anexado com NULL para a respectiva outra coluna (sem sobreposição entre os dois). Então, só precisamos de um INSERT
em vez de dois. Otimização menor. dm_name
e rm_name
podem coexistir
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;
Observações
Ambas as versões também funcionam se nenhuma delas existir.
INSERT
não insere nada se o SELECT
não retorna linha(s). Se você tiver que lidar com acesso de gravação simultâneo que possa entrar em conflito com essa operação, a solução rápida seria bloquear as tabelas envolvidas antes de executar essa instrução na mesma transação.