Oto kilka opcji usuwania zduplikowanych wierszy z tabeli w Oracle Database, gdy te wiersze mają klucz podstawowy lub kolumnę unikatowego identyfikatora.
W takich przypadkach klucz podstawowy musi zostać zignorowany podczas porównywania zduplikowanych wierszy (ze względu na fakt, że klucze podstawowe mają unikalne wartości).
Przykładowe dane
Nasze przykłady wykorzystują następujące dane:
SELECT * FROM Dogs;
Wynik:
DOGI | FIRSTNAME | NAZWISKO |
---|---|---|
1 | Kora | Kowalski |
2 | Kora | Kowalski |
3 | Huu | Jones |
4 | kryza | Robinson |
5 | Wag | Johnson |
6 | Wag | Johnson |
7 | Wag | Johnson |
Widzimy, że pierwsze dwa wiersze są duplikatami, podobnie jak ostatnie trzy wiersze.
Id psa
kolumna zawiera unikalne wartości (ponieważ jest to klucz podstawowy tabeli), ale ignorujemy tę kolumnę podczas porównywania duplikatów. Często może się okazać, że będziesz musiał usunąć duplikaty tabel zawierających klucze podstawowe, dlatego poniższe przykłady mogą służyć właśnie do tego.
Opcja 1
Oto nasza pierwsza opcja usuwania duplikatów powyższej tabeli:
DELETE FROM Dogs
WHERE DogId IN (
SELECT DogId FROM Dogs
MINUS SELECT MIN(DogId) FROM Dogs
GROUP BY FirstName, LastName
);
SELECT * FROM Dogs;
Wynik:
DOGI | FIRSTNAME | NAZWISKO |
---|---|---|
1 | Kora | Kowalski |
3 | Huu | Jones |
4 | kryza | Robinson |
5 | Wag | Johnson |
Duplikaty zostały usunięte (ale jeden wiersz każdego duplikatu pozostaje).
Alternatywnie możemy użyć MAX()
funkcja zamiast MIN()
funkcja do zmiany, które wiersze są usuwane.
Opcja 2
W tym przykładzie (i w poniższych przykładach) założymy, że tabela została przywrócona do swojego pierwotnego stanu (z duplikatami).
Oto kolejny przykład, który usuwa duplikat tabeli, a następnie zaznacza pozostałe wiersze:
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;
Wynik:
DOGI | FIRSTNAME | NAZWISKO |
---|---|---|
2 | Kora | Kowalski |
3 | Huu | Jones |
4 | kryza | Robinson |
7 | Wag | Johnson |
Zauważ, że użyłem MAX()
funkcja zamiast MIN()
którego użyłem w poprzednim przykładzie. Widzimy wpływ, jaki ma to na operację usuwania duplikatów. Usunął różne wiersze z tabeli.
Opcja 3
Oto opcja, która nie wymaga użycia MIN()
lub 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;
Wynik:
DOGI | FIRSTNAME | NAZWISKO |
---|---|---|
1 | Kora | Kowalski |
3 | Huu | Jones |
4 | kryza | Robinson |
5 | Wag | Johnson |
Opcja 4
Oto kolejna opcja:
DELETE FROM Dogs
WHERE DogId > (
SELECT MIN(DogId) FROM Dogs d2
WHERE Dogs.FirstName = d2.FirstName
AND Dogs.LastName = d2.LastName
);
SELECT * FROM Dogs;
Wynik:
DOGI | FIRSTNAME | NAZWISKO |
---|---|---|
1 | Kora | Kowalski |
3 | Huu | Jones |
4 | kryza | Robinson |
5 | Wag | Johnson |
Opcja 5
Każdy wiersz w Oracle ma rowid
pseudokolumna, która zwraca adres wiersza. rowid
jest unikalnym identyfikatorem wierszy w tabeli i zwykle jego wartość jednoznacznie identyfikuje wiersz w bazie danych (chociaż należy pamiętać, że wiersze w różnych tabelach, które są przechowywane razem w tym samym klastrze, mogą mieć ten sam rowid ).
Możemy zatem użyć rowid
w naszym zapytaniu zamiast DogId
kolumna:
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;
Wynik:
DOGI | FIRSTNAME | NAZWISKO |
---|---|---|
1 | Kora | Kowalski |
3 | Huu | Jones |
4 | kryza | Robinson |
5 | Wag | Johnson |
Chociaż ten przykład może wydawać się nieco zbędny, biorąc pod uwagę, że mamy już kolumnę klucza podstawowego, mogą wystąpić sytuacje, w których wolisz użyć rowid
. rowid
może być przydatne, jeśli z jakiegoś powodu nie możesz użyć kolumny klucza podstawowego lub jeśli tabela nie ma klucza podstawowego. Ponadto dokumentacja Oracle wspomina, że rowid
wartości to najszybszy sposób na dostęp do pojedynczego wiersza.
Opcja 6
A oto drugi przykład, ale z rowid
zamiast klucza podstawowego:
DELETE FROM Dogs
WHERE rowid > (
SELECT MIN(rowid) FROM Dogs d2
WHERE Dogs.FirstName = d2.FirstName
AND Dogs.LastName = d2.LastName
);
SELECT * FROM Dogs;
Wynik:
DOGI | FIRSTNAME | NAZWISKO |
---|---|---|
1 | Kora | Kowalski |
3 | Huu | Jones |
4 | kryza | Robinson |
5 | Machać | Johnson |