Evitar a ocorrência de registros duplicados garante a integridade de um banco de dados, pra isso, planejar e prever situações no ato da modelagem do banco são imprescindíveis para não ter dor de cabeça.
No entanto, é comum nos deparamos com bases de dados repletas de registros duplicados, o que pode ter ocorrido por conta de um mal planejamento ou, forçado devido a importação de dados externos.
Localizar e eliminar estes registros, será o que veremos neste artigo.
- Simulando Registros Duplicados
A forma mais simples de localizar os duplicados é através dos comandos GROUP BY e HAVING. Vamos popular uma tabela de produtos a fim de duplicar registros:
Create Tableproduto ( id_produtobigint not null, descricaovarchar(100), estoqueint not null default0 ) ;
Insert IntoprodutoValues(1,"Produto A", 10), (2,"Produto B", 10), (3,"Produto C", 10), (4,"Produto B", 12), (5,"Produto C", 8), (6,"Produto D", 10), (7,"Produto E", 10), (8,"Produto E", 10), (9,"Produto F", 10);
- Identificando os Duplicados
Vejam que os produtos B, C e E estão duplicados, vamos então apresenta-los utilizando um simples select:
select*fromprodutogroup bydescricaohavingcount(descricao) > 1 ;
id_produto descricao estoque
---------- --------- -------
2 Produto B 10
3 Produto C 10
7 Produto E 10
Localizar os registros foi possível pois, agrupamos os diferentes produtos em um só (group by), após, adicionamos a condição para que somente os registros que contenham mais de uma ocorrência (having…) fossem apresentados. (Mais de uma ocorrência após agrupado). No exemplo, filtramos somente os registros com mais de uma ocorrência, mas você pode especificar a quantidade desejada.
[Dica]
Observe que os registros encontrados como duplicados foram os com menor id.
Além de lista-los, podemos identificar todos eles e, saber quantas vezes cada um está repetido, vejamos:
selectdescricao,count(descricao)asQuantidadefromprodutogroup bydescricaohavingcount(descricao) > 1 ;
descricao Quantidade
--------- ----------
Produto B 2
Produto C 2
Produto E 2
Com o count, agora sabemos que para cada registro duplicado, existem duas linhas em nossa tabela.
Agora que já sabemos como identificar os registros, como excluí-los?
- Excluindo os Duplicados
Precauções a parte, vamos excluir os registros. Podemos fazer isso de várias formas, focarei somente na forma mais prática e usual que aplico:
1º – Crio uma tabela com os registros duplicados, esta tabela pode ser apagada posteriormente, no entanto, recomendo não fazer isso, pois, ela pode ser usada posteriormente para fins de consulta:
create tableproduto_duplicado (select*fromprodutogroup bydescricaohavingcount(descricao) > 1) ;
Não entendeu a forma que criei a tabela? Leia esta matéria que entenderá: Criando uma tabela com base em outra já existente.
Lembra da dica que dei acima? Então, neste momento você pode optar por excluir os registros mais antigos, ou mais recentes, no caso, se preferir manter os mais antigos, coloque um max na coluna id_produto.
2º – Com a tabela criada, excluiremos os registros:
deletefromprodutowhereproduto.id_produtoin(selectproduto_duplicado.id_produtofromproduto_duplicadowhereproduto_duplicado.id_produto = produto.id_produto) ;
Nenhum segredo na linha do delete, o x da questão está na tabela que criamos, usamos ela em um sub-select, desta forma, apagamos somente os registros duplicados.
Caso tenha ficado alguma dúvida, queira dar uma sugestão ou reclamar também (:d), poste nos comentários, terei o maior prazer em responder, um grande abraço.
- Perguntas Frequentes
Você menciona que existem outras formas de excluir os registros, quais?
- http://www.devmedia.com.br/forum/como-retornar-e-excluir-registros-duplicados-via-select/32873
- http://msmvps.com/blogs/cmattos/archive/2011/05/07/sql-como-excluir-registros-duplicados-numa-tabela-sem-chave-prim-225-ria.aspx
- http://gustavomaiaaguiar.wordpress.com/2009/05/30/como-eliminar-linhas-duplicadas-e-repeticoes-no-sql-server/
- http://ericsilva.wordpress.com/2013/07/11/como-excluir-registros-duplicados-no-mysql/
Você menciona on delete cascade, o que é isso?
http://magaweb.com.br/blog/?p=450
No seu caso, existem apenas dois registros duplicados para cada produto, se houvessem mais, como eu faria para manter somente um?
Crie uma tabela com os registros que serão mantidos (vide exemplo no 4º link da primeira pergunta), após, apague os registros com o delete apresentado acima (Adaptações poderão ser necessárias).

Olá, eu também uso (dentre outros bancos de dados) o SQL Server. Eu o uso muito para tratar dados em processos de migração de sistemas – clientes que mudam seus programas para outro fornecedor; o SQL Server é perfeito pra mim. Essa questão de linhas duplicadas é uma pegadinha, especialmente porque cada situação traz um cenário particular. Acabei de resolver um problema que estava me “torrando o juízo”: precisei juntar duas tabelas com UNION em uma terceira tabela, onde criei um campo “chave” do tipo IDENTITY (autonumeração ou sequencial do SQL Server), já que eu tinha “id’s” repetidos para os mesmos clientes/fornecedores, no entanto, teria que eliminar as duplicidades mesmo assim. Observando bem, vi que poderia usar duas colunas como critério de desempate: o nome e o CNPJ, e eis o script que usei pra resolver este problema:
delete from pessoa where chave in (select dup.chave from
(select nome, cpf_cnpj, max(chave) as chave, COUNT(*) as contador from pessoa
group by nome, cpf_cnpj
having COUNT(*) > 1) dup)
Espero poder ajudar a outros com o mesmo problema.
DEIXE UM COMENTÁRIO
Ao usar o seguinte comando:
create table produto_duplicado
(select
*
from
produto
group by descricao
having count(descricao) > 1) ;
ELE ME RETORNA A SEGUINTE MENSAGEM:
ERRO: erro de sintaxe em ou próximo a "select"
LINE 2: (select
^
********** Error **********
ERRO: erro de sintaxe em ou próximo a "select"
SQL state: 42601
Character: 39
Podes me ajudar? agradeçop
select * INTO DUPLICADA
from
produto
group by descricao
having count(descricao) > 1) ;