Hier sind einige Optionen zum Löschen doppelter Zeilen aus einer Tabelle in Oracle Database, wenn diese Zeilen einen Primärschlüssel oder eine eindeutige Kennungsspalte haben.
In solchen Fällen muss der Primärschlüssel beim Vergleich doppelter Zeilen ignoriert werden (aufgrund der Tatsache, dass Primärschlüssel eindeutige Werte enthalten).
Beispieldaten
Unsere Beispiele verwenden die folgenden Daten:
SELECT * FROM Dogs;
Ergebnis:
HUNDID | VORNAME | NACHNAME |
---|---|---|
1 | Rillen | Smith |
2 | Rillen | Smith |
3 | Wuff | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
6 | Wag | Johnson |
7 | Wag | Johnson |
Wir können sehen, dass die ersten beiden Zeilen Duplikate sind, ebenso wie die letzten drei Zeilen.
Die DogId
-Spalte enthält eindeutige Werte (weil es der Primärschlüssel der Tabelle ist), aber wir ignorieren diese Spalte beim Vergleichen von Duplikaten. Möglicherweise müssen Sie Tabellen, die Primärschlüssel enthalten, häufig deduplizieren, und daher können die folgenden Beispiele verwendet werden, um genau das zu tun.
Option 1
Hier ist unsere erste Option zum Deduplizieren der obigen Tabelle:
DELETE FROM Dogs
WHERE DogId IN (
SELECT DogId FROM Dogs
MINUS SELECT MIN(DogId) FROM Dogs
GROUP BY FirstName, LastName
);
SELECT * FROM Dogs;
Ergebnis:
HUNDID | VORNAME | NACHNAME |
---|---|---|
1 | Rillen | Smith |
3 | Wuff | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
Die Duplikate wurden entfernt (aber eine Zeile jedes Duplikats bleibt).
Wir können alternativ den MAX()
verwenden anstelle von MIN()
Funktion, um zu ändern, welche Zeilen gelöscht werden.
Option 2
In diesem Beispiel (und den folgenden Beispielen) gehen wir davon aus, dass die Tabelle in ihrem ursprünglichen Zustand (mit den Duplikaten) wiederhergestellt wurde.
Hier ist ein weiteres Beispiel, das die Tabelle dedupliziert und dann die verbleibenden Zeilen auswählt:
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;
Ergebnis:
HUNDID | VORNAME | NACHNAME |
---|---|---|
2 | Rillen | Smith |
3 | Wuff | Jones |
4 | Ruff | Robinson |
7 | Wag | Johnson |
Beachten Sie, dass ich MAX()
verwendet habe Funktion anstelle von MIN()
die ich im vorherigen Beispiel verwendet habe. Wir können die Auswirkungen sehen, die dies auf den Deduplizierungsvorgang hat. Es löschte verschiedene Zeilen aus der Tabelle.
Option 3
Hier ist eine Option, die keine Verwendung von MIN()
erfordert oder 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;
Ergebnis:
HUNDID | VORNAME | NACHNAME |
---|---|---|
1 | Rillen | Smith |
3 | Wuff | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
Option 4
Hier ist eine weitere 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;
Ergebnis:
HUNDID | VORNAME | NACHNAME |
---|---|---|
1 | Rillen | Smith |
3 | Wuff | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
Option 5
Jede Zeile in Oracle hat eine rowid
Pseudospalte, die die Adresse der Zeile zurückgibt. Die rowid
ist ein eindeutiger Bezeichner für Zeilen in der Tabelle, und normalerweise identifiziert sein Wert eine Zeile in der Datenbank eindeutig (obwohl es wichtig ist zu beachten, dass Zeilen in verschiedenen Tabellen, die zusammen im selben Cluster gespeichert sind, dieselbe rowid
).
Wir können daher die rowid
verwenden in unserer Abfrage anstelle der DogId
Spalte:
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;
Ergebnis:
HUNDID | VORNAME | NACHNAME |
---|---|---|
1 | Rillen | Smith |
3 | Wuff | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
Obwohl dieses Beispiel etwas überflüssig erscheinen mag, da wir bereits eine Primärschlüsselspalte haben, kann es Fälle geben, in denen Sie die rowid
bevorzugen . Die rowid
kann nützlich sein, wenn Sie die Primärschlüsselspalte aus irgendeinem Grund nicht verwenden können oder wenn die Tabelle keinen Primärschlüssel hat. Außerdem erwähnt die Dokumentation von Oracle diese rowid
Werte sind der schnellste Weg, um auf eine einzelne Zeile zuzugreifen.
Option 6
Und hier ist das andere Beispiel, aber mit rowid
anstelle des Primärschlüssels:
DELETE FROM Dogs
WHERE rowid > (
SELECT MIN(rowid) FROM Dogs d2
WHERE Dogs.FirstName = d2.FirstName
AND Dogs.LastName = d2.LastName
);
SELECT * FROM Dogs;
Ergebnis:
HUNDID | VORNAME | NACHNAME |
---|---|---|
1 | Rillen | Smith |
3 | Wuff | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |