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
-
Nel 1° CTE
plan
, identifica una riga principale in ogni partizione con lo stessocdesc
. Nel tuo caso la riga con il minimorecid
. -
Nel 2° CTE
upd_lab
reindirizza tutte le righe che fanno riferimento a un duplicato alla riga principale incpt
. -
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: