Her er nogle muligheder for at slette duplikerede rækker fra en tabel i Oracle Database, når disse rækker har en primær nøgle eller en unik identifikatorkolonne.
I sådanne tilfælde skal den primære nøgle ignoreres ved sammenligning af duplikerede rækker (på grund af det faktum, at primærnøgler har unikke værdier).
Eksempeldata
Vores eksempler bruger følgende data:
SELECT * FROM Dogs;
Resultat:
DOGID | FIRSTNAME | Efternavn |
---|---|---|
1 | Gø | Smith |
2 | Gø | Smith |
3 | Wuf | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
6 | Wag | Johnson |
7 | Wag | Johnson |
Vi kan se, at de første to rækker er dubletter, ligesom de sidste tre rækker.
DogId
kolonne indeholder unikke værdier (fordi det er tabellens primære nøgle), men vi ignorerer den kolonne, når vi sammenligner dubletter. Du kan ofte opleve, at du har brug for at de-dupere tabeller, der indeholder primærnøgler, og derfor kan følgende eksempler bruges til netop det.
Valgmulighed 1
Her er vores første mulighed for at de-dupere ovenstående tabel:
DELETE FROM Dogs
WHERE DogId IN (
SELECT DogId FROM Dogs
MINUS SELECT MIN(DogId) FROM Dogs
GROUP BY FirstName, LastName
);
SELECT * FROM Dogs;
Resultat:
DOGID | FIRSTNAME | Efternavn |
---|---|---|
1 | Gø | Smith |
3 | Wuf | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
Dubletterne er blevet fjernet (men der er en række tilbage af hvert duplikat).
Vi kan alternativt bruge MAX()
funktion i stedet for MIN()
funktion for at ændre, hvilke rækker der slettes.
Valgmulighed 2
I dette eksempel (og de følgende eksempler) antager vi, at tabellen er blevet gendannet til sin oprindelige tilstand (med dubletterne).
Her er et andet eksempel, der de-duperer tabellen og derefter vælger de resterende rækker:
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;
Resultat:
DOGID | FIRSTNAME | Efternavn |
---|---|---|
2 | Gø | Smith |
3 | Wuf | Jones |
4 | Ruff | Robinson |
7 | Wag | Johnson |
Bemærk, at jeg brugte MAX()
funktion i stedet for MIN()
som jeg brugte i det forrige eksempel. Vi kan se, hvilken indflydelse dette har på de-duping-operationen. Det slettede forskellige rækker fra tabellen.
Valgmulighed 3
Her er en mulighed, der ikke kræver brug af MIN()
eller 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;
Resultat:
DOGID | FIRSTNAME | Efternavn |
---|---|---|
1 | Gø | Smith |
3 | Wuf | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
Valgmulighed 4
Her er en anden mulighed:
DELETE FROM Dogs
WHERE DogId > (
SELECT MIN(DogId) FROM Dogs d2
WHERE Dogs.FirstName = d2.FirstName
AND Dogs.LastName = d2.LastName
);
SELECT * FROM Dogs;
Resultat:
DOGID | FIRSTNAME | Efternavn |
---|---|---|
1 | Gø | Smith |
3 | Wuf | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
Valgmulighed 5
Hver række i Oracle har en rowid
pseudokolonne, der returnerer adressen på rækken. rovid
er en unik identifikator for rækker i tabellen, og normalt identificerer dens værdi entydigt en række i databasen (selvom det er vigtigt at bemærke, at rækker i forskellige tabeller, der er gemt sammen i den samme klynge, kan have den samme række kode> ).
Vi kan derfor bruge rovid
i vores forespørgsel i stedet for DogId
kolonne:
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;
Resultat:
DOGID | FIRSTNAME | Efternavn |
---|---|---|
1 | Gø | Smith |
3 | Wuf | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
Selvom dette eksempel kan virke lidt overflødigt, da vi allerede har en primær nøglekolonne, kan der være tilfælde, hvor du foretrækker at bruge rovid
. rovid
kan være nyttigt, hvis du af en eller anden grund ikke kan bruge den primære nøglekolonne, eller hvis tabellen ikke har en primærnøgle. Oracles dokumentation nævner også, at rowid
værdier er den hurtigste måde at få adgang til en enkelt række på.
Valgmulighed 6
Og her er det andet eksempel, men med rovid
i stedet for den primære nøgle:
DELETE FROM Dogs
WHERE rowid > (
SELECT MIN(rowid) FROM Dogs d2
WHERE Dogs.FirstName = d2.FirstName
AND Dogs.LastName = d2.LastName
);
SELECT * FROM Dogs;
Resultat:
DOGID | FIRSTNAME | Efternavn |
---|---|---|
1 | Gø | Smith |
3 | Wuf | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |