PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Come rimuovere le righe duplicate con dipendenze di chiavi esterne?

Puoi farlo in modo molto più efficiente con una istruzione SQL singola con CTE di modifica dei dati .

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<>violino qui (pag. 11)
SQL Fiddle (pag. 9.6)

Dovrebbe essere molto più veloce e più pulito. Il ciclo è relativamente costoso, la gestione delle eccezioni è relativamente ancora più costosa.
Ancora più importante, i riferimenti in lab vengono reindirizzati alla rispettiva riga principale in cpt automaticamente, che non era ancora nel codice originale. Quindi puoi eliminare tutti i duplicati in una volta .

Puoi ancora racchiuderlo in una funzione plpgsql o SQL, se lo desideri.

Spiegazione

  1. Nel 1° CTE plan , identifica una riga principale in ogni partizione con lo stesso cdesc . Nel tuo caso la riga con il minimo recid .

  2. Nel 2° CTE upd_lab reindirizza tutte le righe che fanno riferimento a un duplicato alla riga principale in cpt .

  3. Infine, elimina i duplicati, che non solleveranno eccezioni perché le righe dipendenti vengono collegate alla riga principale rimanente praticamente contemporaneamente.

ON DELETE RESTRICT

Tutti i CTE e la query principale di un dichiarazione operare sulla stessa istantanea delle tabelle sottostanti, virtualmente contemporaneamente . Non vedono gli effetti reciproci sulle tabelle sottostanti:

Ci si potrebbe aspettare un vincolo FK con ON DELETE RESTRICT sollevare eccezioni perché, [per documentazione][3]:

Tuttavia, l'istruzione di cui sopra è un comando singolo e, [di nuovo il manuale][3]:

Enfasi in grassetto mio. Funziona per l'impostazione predefinita meno restrittiva ON DELETE NO ACTION anche, ovviamente.

Ma fai attenzione alle transazioni simultanee che scrivono nelle stesse tabelle, ma questa è una considerazione generale, non specifica per questo compito.

Si applica un'eccezione per UNIQUE e PRIMARY KEY vincolo, ma questo non riguarda questo caso: