Consultor Eletrônico



Kbase 47700: Como eliminar registros duplicados em Oracle
Autor   Eloi Rene Pscheidt - CAT
Acesso   Público
Publicação   11/03/2014
O procedimento a seguir poderá ser utilizado para eliminar de uma determinada tabela os registros duplicados com base em um índice único.
Obviamente este procedimento causará perda de dados. Utilizar somente se o registro inteiro estiver duplicado e se estas duplicidades estiverem realmente incorretas.

Neste exemplo, utilizaremos o seguinte cenário:

SQL> select * from teste;

C1 C2
---------- ----------
1 1
1 1
1 1
2 2
2 2
2 2
3 3
3 3
3 3

9 rows selected.

A coluna C1 não deveria apresentar valores duplicados.

Para validar se o registro inteiro está duplicado, utilize o seguinte comando:
SQL> select c1, c2, count(*) from teste group by c1, c2 having count(*) > 1;

C1 C2 COUNT(*)
---------- ---------- ----------
1 1 3
2 2 3
3 3 3

Esta consulta não deve retornar valores duplicados na coluna desejada (C1). Todos os campos da tabela devem ser referenciados nas cláusulas SELECT e GROUP BY.

Tentar criar um índice único nesta coluna causará o erro abaixo:
SQL> create unique index teste_unique on teste (c1);
create unique index teste_unique on teste (c1)
*
ERROR at line 1:
ORA-01452: cannot CREATE UNIQUE INDEX; duplicate keys found

Para corrigir esta situação, renomeie a tabela para um nome temporário:
SQL> rename teste to teste_old;

Table renamed.

Crie a tabela novamente contendo apenas a estrutura da tabela antiga, sem os registros:
SQL> create table teste as select * from teste_old where 1=2;

Table created.

Crie o índice único antes de inserir os registros:
SQL> create unique index teste_unique on teste (c1);

Index created.

Execute o seguinte código PL/SQL:
SQL> begin
2 for c in (select c1, c2 from teste_old) loop
3 begin
4 insert into teste (c1, c2) values(c.c1, c.c2);
5 exception
6 when DUP_VAL_ON_INDEX then null;
7 end;
8 end loop;
9 end;
10 /

PL/SQL procedure successfully completed.

O resultado será a tabela apenas com os registros corretos:
SQL> select * from teste;

C1 C2
---------- ----------
1 1
2 2
3 3

A tabela antiga poderá ser eliminada:
SQL> drop table teste_old;

Table dropped.

Confirme que o referido índice ficou ativo para a tabela:
SQL> select index_name, table_name, status, uniqueness from user_indexes where table_name = 'TESTE';

INDEX_NAME TABLE_NAME STATUS UNIQUENES
------------------------------ ------------------------------ -------- ---------
TESTE_UNIQUE TESTE VALID UNIQUE

Tags: unique constraint duplicate rows delete