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