U kunt dit veel efficiënter doen met een enkele SQL-instructie met gegevensmodificerende CTE's .
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 hier
(pg 11)
SQL Fiddle
(pag. 9.6)
Dit zou veel moeten zijn sneller en schoner. Looping is relatief duur, het afhandelen van uitzonderingen is relatief nog duurder.
Belangrijker, referenties in lab
worden doorgestuurd naar de respectievelijke hoofdrij in cpt
automatisch, wat nog niet in je originele code stond. U kunt dus alle dupes in één keer verwijderen .
Je kunt dit nog steeds verpakken in een plpgsql- of SQL-functie als je wilt.
Uitleg
-
In het 1e CTE
plan
, identificeer een hoofdrij in elke partitie met dezelfdecdesc
. In jouw geval de rij met de minimalerecid
. -
In de 2e CTE
upd_lab
stuur alle rijen die naar een dupe verwijzen om naar de hoofdrij incpt
. -
Verwijder ten slotte dupes, wat geen uitzonderingen oplevert omdat afhankelijke rijen vrijwel tegelijkertijd worden gekoppeld aan de resterende hoofdrij.
ON DELETE RESTRICT
Alle CTE's en de hoofdquery van een instructie werken op dezelfde momentopname van onderliggende tabellen, vrijwel gelijktijdig . Ze zien elkaars effecten op onderliggende tabellen niet:
Je zou een FK-beperking kunnen verwachten met ON DELETE RESTRICT
om uitzonderingen te maken omdat, [per documentatie][3]:
De bovenstaande instructie is echter een enkele opdracht en, [weer de handleiding][3]:
Vetgedrukte nadruk van mij. Werkt voor de minder beperkende standaard ON DELETE NO ACTION
natuurlijk ook.
Maar wees op uw hoede voor gelijktijdige transacties die naar dezelfde tabellen schrijven, maar dat is een algemene overweging, niet specifiek voor deze taak.
Er geldt een uitzondering voor UNIQUE
en PRIMARY KEY
beperking, maar dat heeft geen betrekking op dit geval: