PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Wie entferne ich doppelte Zeilen mit Fremdschlüsselabhängigkeiten?

Sie können dies viel effizienter mit einer einzelnen SQL-Anweisung tun mit datenmodifizierende CTEs .

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 (Seite 11)
SQL Fiddle (Seite 9.6)

Das sollte viel sein schneller und sauberer. Looping ist vergleichsweise teuer, Ausnahmebehandlung ist vergleichsweise noch teurer.
Wichtiger noch, Referenzen im lab werden in cpt in die jeweilige Hauptzeile umgeleitet automatisch, was noch nicht in Ihrem ursprünglichen Code enthalten war. Sie können also alle Duplikate auf einmal löschen .

Sie können dies immer noch in eine plpgsql- oder SQL-Funktion packen, wenn Sie möchten.

Erklärung

  1. Im 1. CTE plan , identifizieren Sie eine Hauptzeile in jeder Partition mit demselben cdesc . In Ihrem Fall die Zeile mit dem Minimum recid .

  2. Im 2. CTE upd_lab leitet alle Zeilen, die auf ein Dupe verweisen, in die Hauptzeile in cpt um .

  3. Löschen Sie schließlich Dupes, was keine Ausnahmen hervorrufen wird, da abhängige Zeilen praktisch gleichzeitig mit der verbleibenden Master-Zeile verknüpft werden.

ON DELETE RESTRICT

Alle CTEs und die Hauptabfrage einer Anweisung auf demselben Snapshot der zugrunde liegenden Tabellen praktisch gleichzeitig arbeiten . Sie sehen die Auswirkungen der anderen auf die zugrunde liegenden Tabellen nicht:

Man könnte eine FK-Einschränkung mit ON DELETE RESTRICT erwarten Ausnahmen auslösen, weil [per Dokumentation][3]:

Die obige Anweisung ist jedoch ein einzelner Befehl und [nochmals das Handbuch][3]:

Fette Hervorhebung von mir. Funktioniert für die weniger restriktive Standardeinstellung ON DELETE NO ACTION natürlich auch.

Aber seien Sie vorsichtig bei gleichzeitigen Transaktionen, die in dieselben Tabellen schreiben, aber das ist eine allgemeine Überlegung, nicht spezifisch für diese Aufgabe.

Eine Ausnahme gilt für UNIQUE und PRIMARY KEY Beschränkung, aber das betrifft das nicht Fall: