Hier zijn enkele opties voor het verwijderen van dubbele rijen uit een tabel in Oracle Database wanneer die rijen een primaire sleutel of een unieke id-kolom hebben.
In dergelijke gevallen moet de primaire sleutel worden genegeerd bij het vergelijken van dubbele rijen (vanwege het feit dat primaire sleutels unieke waarden bevatten).
Voorbeeldgegevens
Onze voorbeelden gebruiken de volgende gegevens:
SELECT * FROM Dogs;
Resultaat:
HONDEN-ID | FIRSTNAME | Achternaam |
---|---|---|
1 | Bark | Smith |
2 | Bark | Smith |
3 | Inslag | Jones |
4 | Kemmel | Robinson |
5 | Kwispelen | Johnson |
6 | Kwispelen | Johnson |
7 | Kwispelen | Johnson |
We kunnen zien dat de eerste twee rijen duplicaten zijn, net als de laatste drie rijen.
De DogId
kolom unieke waarden bevat (omdat het de primaire sleutel van de tabel is), maar we negeren die kolom bij het vergelijken van duplicaten. U zult vaak merken dat u tabellen moet ontdubbelen die primaire sleutels bevatten, en daarom kunnen de volgende voorbeelden worden gebruikt om precies dat te doen.
Optie 1
Dit is onze eerste optie om de bovenstaande tabel te ontdubbelen:
DELETE FROM Dogs
WHERE DogId IN (
SELECT DogId FROM Dogs
MINUS SELECT MIN(DogId) FROM Dogs
GROUP BY FirstName, LastName
);
SELECT * FROM Dogs;
Resultaat:
HONDEN-ID | FIRSTNAME | Achternaam |
---|---|---|
1 | Bark | Smith |
3 | Inslag | Jones |
4 | Kemmel | Robinson |
5 | Kwispelen | Johnson |
De duplicaten zijn verwijderd (maar van elk duplicaat blijft er één rij over).
We kunnen ook de MAX()
. gebruiken functie in plaats van de MIN()
functie om te wijzigen welke rijen worden verwijderd.
Optie 2
In dit voorbeeld (en de volgende voorbeelden) gaan we ervan uit dat de tabel in de oorspronkelijke staat is hersteld (met de duplicaten).
Hier is nog een voorbeeld dat de tabel ontdubbelt en vervolgens de resterende rijen selecteert:
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;
Resultaat:
HONDEN-ID | FIRSTNAME | Achternaam |
---|---|---|
2 | Bark | Smith |
3 | Inslag | Jones |
4 | Kemmel | Robinson |
7 | Kwispelen | Johnson |
Merk op dat ik de MAX()
. heb gebruikt functie in plaats van MIN()
die ik in het vorige voorbeeld heb gebruikt. We kunnen zien welk effect dit heeft op de ontdubbelingsoperatie. Het heeft verschillende rijen uit de tabel verwijderd.
Optie 3
Hier is een optie die het gebruik van MIN()
. niet vereist of 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;
Resultaat:
HONDEN-ID | FIRSTNAME | Achternaam |
---|---|---|
1 | Bark | Smith |
3 | Inslag | Jones |
4 | Kemmel | Robinson |
5 | Kwispelen | Johnson |
Optie 4
Hier is nog een optie:
DELETE FROM Dogs
WHERE DogId > (
SELECT MIN(DogId) FROM Dogs d2
WHERE Dogs.FirstName = d2.FirstName
AND Dogs.LastName = d2.LastName
);
SELECT * FROM Dogs;
Resultaat:
HONDEN-ID | FIRSTNAME | Achternaam |
---|---|---|
1 | Bark | Smith |
3 | Inslag | Jones |
4 | Kemmel | Robinson |
5 | Kwispelen | Johnson |
Optie 5
Elke rij in Oracle heeft een rowid
pseudokolom die het adres van de rij retourneert. De rowid
is een unieke id voor rijen in de tabel, en gewoonlijk identificeert de waarde ervan een rij in de database op unieke wijze (hoewel het belangrijk is op te merken dat rijen in verschillende tabellen die samen in hetzelfde cluster zijn opgeslagen dezelfde rowid ).
We kunnen daarom de rowid
. gebruiken in onze zoekopdracht in plaats van de DogId
kolom:
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;
Resultaat:
HONDEN-ID | FIRSTNAME | Achternaam |
---|---|---|
1 | Bark | Smith |
3 | Inslag | Jones |
4 | Kemmel | Robinson |
5 | Kwispelen | Johnson |
Hoewel dit voorbeeld enigszins overbodig lijkt, aangezien we al een primaire sleutelkolom hebben, kunnen er gevallen zijn waarin u liever de rowid
gebruikt . De rowid
kan handig zijn als u de primaire sleutelkolom om de een of andere reden niet kunt gebruiken, of als de tabel geen primaire sleutel heeft. De documentatie van Oracle vermeldt ook dat rowid
waarden zijn de snelste manier om toegang te krijgen tot een enkele rij.
Optie 6
En hier is het andere voorbeeld, maar met rowid
in plaats van de primaire sleutel:
DELETE FROM Dogs
WHERE rowid > (
SELECT MIN(rowid) FROM Dogs d2
WHERE Dogs.FirstName = d2.FirstName
AND Dogs.LastName = d2.LastName
);
SELECT * FROM Dogs;
Resultaat:
HONDEN-ID | FIRSTNAME | Achternaam |
---|---|---|
1 | Bark | Smith |
3 | Inslag | Jones |
4 | Kemmel | Robinson |
5 | Kwispelen | Johnson |