Do not duplicate

Non vuole essere una presa di posizione sulla pirateria

Quando si lavora con i database, può capitare di scegliere male la chiave di una tabella (o peggio di non sceglierne nessuna!) e a un certo punto ritrovarsi con numerosi record duplicati da cancellare.

Ci sono svariate procedure possibili per farlo. Personalmente ritengo la seguente la più semplice.

Premessa più che straimportante: cancellare record da un database è sempre un’operazione rischiosa. Per carità, fai un backup del database prima di agire!

Seconda premessa più che straimportante: cancellare record da un database è sempre un’operazione rischiosa. Per carità, fai un backup del database prima di agire! (repetita iuvant)

Lo scenario di questo esempio è il seguente (lo so: è stupido ma non voglio complicare inutilmente le cose):

Abbiamo una tabella Persone dove vanno cancellati gli omonimi.

Ecco i passi da seguire:

  1. Crea una tabella temporanea che conterrà i record da cancellare:
    CREATE TEMPORARY TABLE to_delete
    (`ID` int(10) not null,
    `nome` varchar(200) not null,
    `cognome` varchar(200) not null);
  2. Popola la tabella temporanea:
    INSERT INTO to_delete
    (`ID`, `nome`, `cognome`)
    SELECT `ID`, `nome`, `cognome`, MIN(`ID`) AS min_id
    FROM
    (
    SELECT *
    FROM `Persone`
    GROUP BY `nome`, `cognome`
    HAVING COUNT(*) > 1
    ) AS temp
    WHERE TODO;
  3. Cancella davvero i record:
    UPDATE `Persone` SET `deletion_flag`=1
    WHERE EXISTS
    (
    SELECT * FROM `to_delete`
    WHERE `to_delete`.`ID` = `Persone`.`ID`
    AND `Persone`.`ID` != `to_delete`.`min_id`
    );

Alcune dovute precisazioni:

  • L’uso di una tabella temporanea non è strettamente necessario, ma assicura almeno che alla fine della sessione la cartella `to_delete` venga cancellata automaticamente. Da notare che non è possibile usare tabelle temporanee con strumenti come PhpMyAdmin perché usano a ogni operazione una sessione diversa.
  • Nell’ultima query non ho davvero cancellato il record bensì ho impostato un flag che permette la cancellazione logica. Ovviamente ciò prevede che la tua applicazione gestisce la cancellazione logica (è sempre cosa buona e giusta). Se così non fosse puoi banalmente usare una DELETE
  • La cartella temporanea viene popolata con coppie di record duplicati; durante la cancellazione ho scelto di tenere il record con ID massimo. Naturalmente non è sempre questa la scelta corretta: se necessario adatta la query alle tue esigenze.

Sia chiaro che non mi prendo nessuna responsabilità in caso di errori miei o vostri :p1.

Condividi:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • FriendFeed
  • PDF
  • Ping.fm
  • Technorati
  • Twitter
  1. A dirla tutta questo post deve molto a un post analogo in inglese []