sql >> Database >  >> RDS >> PostgreSQL

Hoe dubbele rijen met afhankelijkheden van externe sleutels te verwijderen?

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

  1. In het 1e CTE plan , identificeer een hoofdrij in elke partitie met dezelfde cdesc . In jouw geval de rij met de minimale recid .

  2. In de 2e CTE upd_lab stuur alle rijen die naar een dupe verwijzen om naar de hoofdrij in cpt .

  3. 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:



  1. hoe deze query ook rijen met een waarde van 0 te laten retourneren?

  2. Een PostgreSQL-query exporteren naar een csv-bestand met Python

  3. Een willekeurige uitdrukking uit string verwijderen

  4. Een basisgegevensstructuur modelleren om gebruikers, discussielijnen en berichten te beheren