sql >> Databáze >  >> RDS >> PostgreSQL

Jak odstranit duplicitní řádky se závislostmi na cizích klíčích?

Můžete to udělat mnohem efektivněji pomocí jediného příkazu SQL s CTE upravující data .

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 zde (str. 11)
SQL Fiddle (str. 9.6)

To by mělo být hodně rychlejší a čistší. Opakování je poměrně drahé, zpracování výjimek je poměrně ještě dražší.
Důležitější je, odkazy v lab jsou přesměrováni na příslušný hlavní řádek v cpt automaticky, což ještě nebylo ve vašem původním kódu. Můžete tedy smazat všechny dupy najednou .

Stále to můžete zabalit do funkce plpgsql nebo SQL, pokud chcete.

Vysvětlení

  1. V 1. plan CTE , identifikujte hlavní řádek v každém oddílu se stejným cdesc . Ve vašem případě řádek s minimem recid .

  2. Ve 2. CTE upd_lab přesměrovat všechny řádky odkazující na dupe na hlavní řádek v cpt .

  3. Nakonec smažte dupy, což nebude vyvolávat výjimky, protože závislé řádky jsou propojeny se zbývajícím hlavním řádkem prakticky současně.

ON DELETE RESTRICT

Všechny CTE a hlavní dotaz výkazu pracovat na stejném snímku podkladových tabulek, prakticky současně . Nevidí vzájemný vliv na podkladové tabulky:

Dalo by se očekávat omezení FK s ON DELETE RESTRICT vyvolat výjimky, protože [podle dokumentace][3]:

Výše uvedený příkaz je však jediným příkazem a [znovu manuál][3]:

Odvážný důraz můj. Funguje pro méně omezující výchozí ON DELETE NO ACTION také, samozřejmě.

Dávejte si ale pozor na souběžné transakce zapisující do stejných tabulek, ale to je obecná úvaha, nikoli specifická pro tento úkol.

Výjimka platí pro UNIQUE a PRIMARY KEY omezení, ale to se tohoto netýká případ:



  1. Obnovení metadat o uživatelských funkcích t-SQL

  2. Příkazy MySQL CASE...WHERE...THEN

  3. Jak používat kaskádu mazání na úložišti MySQL MyISAM?

  4. Jak ručně nakonfigurovat server Glassfish v Eclipse