sql >> Databasteknik >  >> RDS >> PostgreSQL

Hur tar man bort dubbletter av rader med främmande nycklar?

Du kan göra detta mycket mer effektivt med en enskild SQL-sats med datamodifierande CTE:er .

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<>fiol här (sid 11)
SQL Fiddle (sid 9.6)

Det här borde vara mycket snabbare och renare. Looping är jämförelsevis dyrt, undantagshantering är jämförelsevis ännu dyrare.
Och ännu viktigare, referenser i lab omdirigeras till respektive huvudrad i cpt automatiskt, vilket inte fanns i din ursprungliga kod ännu. Så du kan ta bort alla duper på en gång .

Du kan fortfarande slå in detta i en plpgsql- eller SQL-funktion om du vill.

Förklaring

  1. I den första CTE plan , identifiera en masterrad i varje partition med samma cdesc . I ditt fall raden med minsta recid .

  2. I den andra CTE upd_lab omdirigera alla rader som hänvisar till en dupe till huvudraden i cpt .

  3. Slutligen, ta bort duper, vilket inte kommer att skapa undantag eftersom beroende rader kopplas till den återstående masterraden praktiskt taget samtidigt.

ON DELETE RESTRICT

Alla CTE:er och huvudfrågan i ett uttalande arbeta på samma ögonblicksbild av underliggande tabeller, praktiskt taget samtidigt . De ser inte varandras effekter på underliggande tabeller:

Man kan förvänta sig en FK-begränsning med ON DELETE RESTRICT att ta upp undantag eftersom, [per dokumentation][3]:

Men uttalandet ovan är ett enkelt kommando och, [manualen igen][3]:

Djärv betoning min. Fungerar för den mindre restriktiva standarden ON DELETE NO ACTION också såklart.

Men var försiktig med samtidiga transaktioner som skrivs till samma tabeller, men det är ett allmänt övervägande, inte specifikt för denna uppgift.

Ett undantag gäller för UNIQUE och PRIMARY KEY begränsning, men det gäller inte det här fall:



  1. PHP-visningsnamn för inloggningsanvändare

  2. COALESCE två datum returnerar binärt?

  3. psql:FATAL:databasen <användare> finns inte

  4. Rails &MSSQL 2008 - Kommer vi att träffa barriärer?