sql >> Database >  >> RDS >> Oracle

6 manieren om dubbele rijen met een primaire sleutel in Oracle te verwijderen

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

  1. Probleem met Oracle-bindvariabelen die index niet correct gebruiken

  2. Hoe de serversortering in MySQL te tonen

  3. Hoe schrijf je een beperking met betrekking tot een maximaal aantal rijen in postgresql?

  4. Trace Flag 3226 gebruiken om logboekregistratie van back-ups te onderdrukken