Supprimer les doublons en conservant la bonne ligne
Définissez la clé métier et la règle de conservation, vérifiez ROW_NUMBER et empêchez le retour des doublons après nettoyage.
La difficulté du dédoublonnage n'est pas d'écrire DELETE. Elle consiste à définir l'identité métier, les informations à préserver et les références qui doivent rester valides. Deux lignes partageant une adresse électronique ne représentent pas forcément la même personne. La plus grande identité n'est pas non plus automatiquement la donnée la plus fiable.
Définir égalité et conservation
Écrivez explicitement la clé métier du doublon. Incluez le locataire ou le système source si nécessaire. Précisez la signification de la casse, des accents, des espaces et des valeurs absentes. Les comparaisons suivent la collation. Regrouper les NULL peut être incorrect lorsque NULL signifie identité inconnue plutôt qu'identité commune.
Choisissez une règle déterministe. Dans l'exercice, TenantId et ExternalKey forment la clé, la ligne observée le plus récemment gagne et RowId départage les horodatages identiques. Ce dernier critère unique évite que plusieurs exécutions choisissent des survivants différents.
Les ExternalKey absents sont volontairement exclus. Chaque identité inconnue reste indépendante jusqu'à un rapprochement spécifique. C'est une politique possible, pas une interprétation universelle de NULL.
CREATE TABLE #CustomerStage
(RowId int PRIMARY KEY, TenantId int NOT NULL,
ExternalKey varchar(20) NULL, SeenAt datetime2(0) NOT NULL);
INSERT #CustomerStage VALUES
(1,1,'A','2020-01-01'),(2,1,'A','2020-02-01'),
(3,2,'A','2020-01-01'),(4,1,NULL,'2020-01-01'),
(5,1,NULL,'2020-02-01');
;WITH ranked AS
( SELECT *, ROW_NUMBER() OVER
(PARTITION BY TenantId, ExternalKey
ORDER BY SeenAt DESC, RowId DESC) AS rn
FROM #CustomerStage WHERE ExternalKey IS NOT NULL )
SELECT * FROM ranked WHERE rn > 1 ORDER BY RowId;
La victime attendue est RowId 1. La ligne 2 est plus récente pour le locataire 1 et la clé A. La ligne 3 appartient à un autre locataire, tandis que 4 et 5 ont une identité inconnue. Faites valider ces résultats avant toute écriture réelle.
Maîtriser le passage à la suppression
L'expérience suivante ne touche que la table temporaire et annule la suppression. OUTPUT capture les lignes effectivement retirées. Après rollback, les données initiales sont intactes. En production, validez d'abord règle, volume, récupération et stratégie de concurrence des écritures.
BEGIN TRAN;
;WITH ranked AS
( SELECT *, ROW_NUMBER() OVER
(PARTITION BY TenantId, ExternalKey
ORDER BY SeenAt DESC, RowId DESC) AS rn
FROM #CustomerStage WHERE ExternalKey IS NOT NULL )
DELETE FROM ranked
OUTPUT deleted.RowId, deleted.TenantId, deleted.ExternalKey
WHERE rn > 1;
ROLLBACK;
Une prévisualisation réalisée plusieurs heures auparavant ne garantit pas la sélection ultérieure. Des lignes peuvent arriver et les horodatages changer. Utilisez une fenêtre contrôlée ou une isolation délibérée couvrant sélection, migration des références, suppression et protection d'unicité. Une grande transaction sérialisable peut bloquer fortement ; elle ne constitue pas une option gratuite.
Inventoriez les clés étrangères et les relations non déclarées avant de supprimer des parents. Si des enfants pointent vers les identités dupliquées, créez une correspondance victime-survivant puis réaffectez-les selon les règles métier. Certains enfants peuvent alors entrer en conflit sur leur propre clé unique. Résolvez ce conflit explicitement au lieu de désactiver les contraintes.
Préserver le sens et éviter le retour
La ligne récente peut contenir une adresse vide et l'ancienne une adresse vérifiée. Une simple sélection perdrait cette information. Fusionnez les attributs suivant des priorités documentées et conservez la provenance nécessaire. Le survivant peut être un enregistrement consolidé plutôt qu'une ligne d'origine inchangée.
Gardez une correspondance auditable et les données retirées nécessaires pendant la période de récupération convenue. Une sauvegarde reste indispensable, mais peut être peu pratique pour restaurer quelques relations après d'autres écritures légitimes. Le dossier de récupération doit identifier les anciennes clés et la transformation, avec les protections appropriées pour les données personnelles.
Après nettoyage, imposez l'unicité réelle par contrainte ou index unique filtré adapté au traitement des clés inconnues. Corrigez aussi la course d'import ou le manque d'idempotence à l'origine du problème. Contrôlez les comptes par locataire, les attributs conservés, les références et la répétition de l'import fautif. Le succès consiste à retirer seulement les vrais doublons, préserver l'information et rejeter la prochaine répétition immédiatement.
Références techniques: Microsoft Learn: ROW_NUMBER · Microsoft Learn: Unique indexes.