Vous pouvez le faire beaucoup plus efficacement avec une instruction SQL unique avec CTE modifiant les données .
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<>violon ici
(page 11)
SQL Fiddle
(page 9.6)
Cela devrait être beaucoup plus rapide et plus propre. Le bouclage est relativement coûteux, la gestion des exceptions est comparativement encore plus coûteuse.
Plus important encore, les références dans lab
sont redirigés vers la ligne maître respective dans cpt
automatiquement, ce qui n'était pas encore dans votre code d'origine. Ainsi, vous pouvez supprimer tous les doublons d'un coup .
Vous pouvez toujours envelopper cela dans une fonction plpgsql ou SQL si vous le souhaitez.
Explication
-
Au 1er CTE
plan
, identifiez une ligne principale dans chaque partition avec le mêmecdesc
. Dans votre cas, la ligne avec le minimumrecid
. -
Au 2ème CTE
upd_lab
rediriger toutes les lignes faisant référence à un dupe vers la ligne principale danscpt
. -
Enfin, supprimez les doublons, ce qui ne déclenchera pas d'exceptions car les lignes dépendantes sont liées à la ligne principale restante pratiquement en même temps.
ON DELETE RESTRICT
Tous les CTE et la requête principale d'un relevé fonctionnent sur le même instantané des tables sous-jacentes, pratiquement simultanément . Ils ne voient pas les effets les uns des autres sur les tables sous-jacentes :
On pourrait s'attendre à une contrainte FK avec ON DELETE RESTRICT
pour lever des exceptions parce que, [selon la documentation][3] :
Cependant, la déclaration ci-dessus est une commande unique et, [le manuel encore][3] :
Bold emphase mienne. Fonctionne pour la valeur par défaut moins restrictive ON DELETE NO ACTION
aussi, bien sûr.
Mais méfiez-vous des transactions simultanées écrivant dans les mêmes tables, mais c'est une considération générale, non spécifique à cette tâche.
Une exception s'applique pour UNIQUE
et PRIMARY KEY
contrainte, mais cela ne concerne ceci cas :