Voici quelques options pour supprimer les lignes en double d'une table dans Oracle Database lorsque ces lignes ont une clé primaire ou une colonne d'identifiant unique.
Dans de tels cas, la clé primaire doit être ignorée lors de la comparaison de lignes en double (en raison du fait que les clés primaires contiennent des valeurs uniques).
Exemple de données
Nos exemples utilisent les données suivantes :
SELECT * FROM Dogs;
Résultat :
DOGID | PRÉNOM | NOM |
---|---|---|
1 | Aboiement | Smith |
2 | Aboiement | Smith |
3 | Ouaf | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
6 | Wag | Johnson |
7 | Wag | Johnson |
Nous pouvons voir que les deux premières lignes sont des doublons, tout comme les trois dernières lignes.
Le DogId
La colonne contient des valeurs uniques (parce que c'est la clé primaire de la table), mais nous ignorons cette colonne lors de la comparaison des doublons. Vous pouvez souvent avoir besoin de dédupliquer des tables contenant des clés primaires, et les exemples suivants peuvent donc être utilisés pour faire exactement cela.
Option 1
Voici notre première option pour dédupliquer le tableau ci-dessus :
DELETE FROM Dogs
WHERE DogId IN (
SELECT DogId FROM Dogs
MINUS SELECT MIN(DogId) FROM Dogs
GROUP BY FirstName, LastName
);
SELECT * FROM Dogs;
Résultat :
DOGID | PRÉNOM | NOM |
---|---|---|
1 | Aboiement | Smith |
3 | Ouaf | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
Les doublons ont été supprimés (mais il reste une ligne de chaque doublon).
Nous pouvons alternativement utiliser le MAX()
fonction au lieu de MIN()
fonction pour changer les lignes à supprimer.
Option 2
Dans cet exemple (et les exemples suivants), nous supposerons que la table a été restaurée dans son état d'origine (avec les doublons).
Voici un autre exemple qui dédouble la table, puis sélectionne les lignes restantes :
DELETE FROM Dogs WHERE DogId IN (
SELECT d2.DogId
FROM Dogs d1, Dogs d2
WHERE d1.FirstName = d2.FirstName
AND d1.LastName = d2.LastName
AND d1.DogId <> d2.DogId
AND d1.DogId=(
SELECT MAX(DogId)
FROM Dogs d3
WHERE d3.FirstName = d1.FirstName
AND d3.LastName = d1.LastName
)
);
SELECT * FROM Dogs;
Résultat :
DOGID | PRÉNOM | NOM |
---|---|---|
2 | Aboiement | Smith |
3 | Ouaf | Jones |
4 | Ruff | Robinson |
7 | Wag | Johnson |
Notez que j'ai utilisé le MAX()
fonction au lieu de MIN()
que j'ai utilisé dans l'exemple précédent. Nous pouvons voir l'effet que cela a sur l'opération de dédoublement. Il a supprimé différentes lignes de la table.
Option 3
Voici une option qui ne nécessite pas l'utilisation de MIN()
ou MAX()
:
DELETE FROM Dogs
WHERE EXISTS (
SELECT 1 FROM Dogs d2
WHERE Dogs.FirstName = d2.FirstName
AND Dogs.LastName = d2.LastName
AND Dogs.DogId > d2.DogId
);
SELECT * FROM Dogs;
Résultat :
DOGID | PRÉNOM | NOM |
---|---|---|
1 | Aboiement | Smith |
3 | Ouaf | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
Option 4
Voici une autre option :
DELETE FROM Dogs
WHERE DogId > (
SELECT MIN(DogId) FROM Dogs d2
WHERE Dogs.FirstName = d2.FirstName
AND Dogs.LastName = d2.LastName
);
SELECT * FROM Dogs;
Résultat :
DOGID | PRÉNOM | NOM |
---|---|---|
1 | Aboiement | Smith |
3 | Ouaf | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
Option 5
Chaque ligne dans Oracle a un rowid
pseudo-colonne qui renvoie l'adresse de la ligne. Le rowid
est un identifiant unique pour les lignes de la table, et généralement sa valeur identifie de manière unique une ligne dans la base de données (bien qu'il soit important de noter que les lignes de différentes tables qui sont stockées ensemble dans le même cluster peuvent avoir le même rowid
).
On peut donc utiliser le rowid
dans notre requête au lieu de DogId
colonne :
DELETE FROM Dogs
WHERE EXISTS (
SELECT 1 FROM Dogs d2
WHERE Dogs.FirstName = d2.FirstName
AND Dogs.LastName = d2.LastName
AND Dogs.rowid > d2.rowid
);
SELECT * FROM Dogs;
Résultat :
DOGID | PRÉNOM | NOM |
---|---|---|
1 | Aboiement | Smith |
3 | Ouaf | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
Bien que cet exemple puisse sembler légèrement superflu, étant donné que nous avons déjà une colonne de clé primaire, il peut y avoir des cas où vous préférez utiliser le rowid
. Le rowid
peut être utile si vous ne pouvez pas utiliser la colonne de clé primaire pour une raison quelconque, ou si la table n'a pas de clé primaire. De plus, la documentation d'Oracle mentionne que rowid
les valeurs sont le moyen le plus rapide d'accéder à une seule ligne.
Option 6
Et voici l'autre exemple, mais avec rowid
au lieu de la clé primaire :
DELETE FROM Dogs
WHERE rowid > (
SELECT MIN(rowid) FROM Dogs d2
WHERE Dogs.FirstName = d2.FirstName
AND Dogs.LastName = d2.LastName
);
SELECT * FROM Dogs;
Résultat :
DOGID | PRÉNOM | NOM |
---|---|---|
1 | Aboiement | Smith |
3 | Ouaf | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |