Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

6 maneiras de excluir linhas duplicadas que têm uma chave primária no Oracle


Aqui estão algumas opções para excluir linhas duplicadas de uma tabela no Oracle Database quando essas linhas têm uma chave primária ou uma coluna de identificador exclusivo.

Nesses casos, a chave primária deve ser ignorada ao comparar linhas duplicadas (devido ao fato de que as chaves primárias contêm valores exclusivos).

Dados de amostra


Nossos exemplos usam os seguintes dados:
SELECT * FROM Dogs;

Resultado:
DOGID PRIMEIRO NOME SOBRENOME
1 Latido Smith
2 Latido Smith
3 Au Jones
4 Ruff Robinson
5 Agite Johnson
6 Agite Johnson
7 Agite Johnson

Podemos ver que as duas primeiras linhas são duplicadas, assim como as três últimas linhas.

O DogId A coluna contém valores exclusivos (porque é a chave primária da tabela), mas estamos ignorando essa coluna ao comparar duplicatas. Muitas vezes, você pode precisar desduplicar tabelas que contêm chaves primárias e, portanto, os exemplos a seguir podem ser usados ​​para fazer exatamente isso.

Opção 1


Aqui está nossa primeira opção para desduplicar a tabela acima:
DELETE FROM Dogs 
WHERE DogId IN (
    SELECT DogId FROM Dogs 
    MINUS SELECT MIN(DogId) FROM Dogs 
    GROUP BY FirstName, LastName
    );

SELECT * FROM Dogs;

Resultado:
DOGID PRIMEIRO NOME SOBRENOME
1 Latido Smith
3 Au Jones
4 Ruff Robinson
5 Agite Johnson

As duplicatas foram removidas (mas uma linha de cada duplicata permanece).

Alternativamente, podemos usar o MAX() função em vez de MIN() função para alterar quais linhas são excluídas.

Opção 2


Neste exemplo (e nos exemplos a seguir), vamos supor que a tabela foi restaurada ao seu estado original (com as duplicatas).

Aqui está outro exemplo que desduplica a tabela e, em seguida, seleciona as linhas restantes:
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;

Resultado:
DOGID PRIMEIRO NOME SOBRENOME
2 Latido Smith
3 Au Jones
4 Ruff Robinson
7 Agite Johnson

Observe que usei o MAX() função em vez de MIN() que usei no exemplo anterior. Podemos ver o efeito que isso tem na operação de desduplicação. Ele excluiu diferentes linhas da tabela.

Opção 3


Aqui está uma opção que não requer o uso de MIN() ou 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;

Resultado:
DOGID PRIMEIRO NOME SOBRENOME
1 Latido Smith
3 Au Jones
4 Ruff Robinson
5 Agite Johnson

Opção 4


Aqui está outra opção:
DELETE FROM Dogs
WHERE DogId > (
  SELECT MIN(DogId) FROM Dogs d2  
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
);

SELECT * FROM Dogs;

Resultado:
DOGID PRIMEIRO NOME SOBRENOME
1 Latido Smith
3 Au Jones
4 Ruff Robinson
5 Agite Johnson

Opção 5


Cada linha no Oracle tem um rowid pseudocoluna que retorna o endereço da linha. O rowid é um identificador exclusivo para linhas na tabela e geralmente seu valor identifica exclusivamente uma linha no banco de dados (embora seja importante observar que linhas em tabelas diferentes armazenadas juntas no mesmo cluster podem ter o mesmo rowid ).

Podemos, portanto, usar o rowid em nossa consulta em vez do DogId coluna:
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;

Resultado:
DOGID PRIMEIRO NOME SOBRENOME
1 Latido Smith
3 Au Jones
4 Ruff Robinson
5 Agite Johnson

Embora este exemplo possa parecer um pouco supérfluo, dado que já temos uma coluna de chave primária, pode haver casos em que você prefira usar o rowid . O rowid pode ser útil se você não puder usar a coluna de chave primária por algum motivo ou se a tabela não tiver uma chave primária. Além disso, a documentação da Oracle menciona que rowid valores são a maneira mais rápida de acessar uma única linha.

Opção 6


E aqui está o outro exemplo, mas com rowid em vez da chave primária:
DELETE FROM Dogs
WHERE rowid > (
  SELECT MIN(rowid) FROM Dogs d2  
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
);

SELECT * FROM Dogs;

Resultado:
DOGID PRIMEIRO NOME SOBRENOME
1 Latido Smith
3 Au Jones
4 Ruff Robinson
5 Agite Johnson