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