PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Como remover linhas duplicadas com dependências de chaves estrangeiras?


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


  1. No 1º CTE plan , identifique uma linha mestra em cada partição com o mesmo cdesc . No seu caso, a linha com o mínimo recid .

  2. No 2º CTE upd_lab redirecione todas as linhas que fazem referência a um dupe para a linha mestra em cpt .

  3. 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: