Você pode fazer isso com muito mais eficiência com uma instrução SQL única com CTEs de modificação de dados .
WITH plan AS (
SELECT *
FROM (
SELECT recid, min(recid) OVER (PARTITION BY cdesc) AS master_recid
FROM cpt
) sub
WHERE recid <> master_recid -- ... <> self
)
, upd_lab AS (
UPDATE lab l
SET cpt_recid = p.master_recid -- link to master recid ...
FROM plan p
WHERE l.cpt_recid = p.recid
)
DELETE FROM cpt c
USING plan p
WHERE c.recid = p.recid
RETURNING c.recid;
db<>fiddle aqui (página 11)
SQL Fiddle (pág. 9.6)
Isso deve ser muito mais rápido e mais limpo. O loop é comparativamente caro, o tratamento de exceções é comparativamente ainda mais caro.
Mais importante, referências em
lab
são redirecionados para a respectiva linha mestra em cpt
automaticamente, que ainda não estava no seu código original. Assim, você pode excluir todos os dupes de uma vez . Você ainda pode envolver isso em uma função plpgsql ou SQL, se desejar.
Explicação
-
No 1º CTEplan
, identifique uma linha mestra em cada partição com o mesmocdesc
. No seu caso, a linha com o mínimorecid
.
-
No 2º CTEupd_lab
redirecione todas as linhas que fazem referência a um dupe para a linha mestra emcpt
.
-
Por fim, exclua os dupes, o que não gerará exceções porque as linhas dependentes estão sendo vinculadas à linha mestra restante praticamente ao mesmo tempo.
ON DELETE RESTRICT
Todos os CTEs e a consulta principal de uma instrução operam no mesmo instantâneo de tabelas subjacentes, virtualmente simultaneamente . Eles não veem os efeitos uns dos outros nas tabelas subjacentes:
Pode-se esperar uma restrição FK com
ON DELETE RESTRICT
para levantar exceções porque, [por documentação][3]:No entanto, a declaração acima é um comando único e, [o manual novamente][3]:
Minha ênfase em negrito. Funciona para o padrão menos restritivo
ON DELETE NO ACTION
também, claro. Mas tenha cuidado com transações simultâneas gravando nas mesmas tabelas, mas essa é uma consideração geral, não específica para essa tarefa.
Uma exceção se aplica a
UNIQUE
e PRIMARY KEY
restrição, mas isso não diz respeito isto caso: