Oracle如何删除表中重复记录

1    引言

在对数据库进行操作过程中我们可能会遇到这种情况,表中的数据可能重复出现,使我们对数据库的操作过程中带来 读诸 多不便,那么怎么删除这些重复没有用的数据呢 ?

创新互联网站建设由有经验的网站设计师、开发人员和项目经理组成的专业建站团队,负责网站视觉设计、用户体验优化、交互设计和前端开发等方面的工作,以确保网站外观精美、网站设计制作、做网站易于使用并且具有良好的响应性。

平时工作中可能会遇到当试图对库表中的某一列或几列创建唯一索引时,系统提示 ORA-01452  :不能创建唯一索引,发现重复记录。

2    处理过程

重复的数据可能有这样两种情况 : 第一种 是 表中只有某些字段一样,第二种是两行记录完全一样 。删除重复记录后的结果也分为 2 种, 第一种 是重复的记录全部删除 ,第二种是 重复的记录中只保留最新的一条记录,一般业务中第二种的情况较多。

 

2.1    删除重复记录的方法原理

(1) 在Oracle 中,每一条记录都有一个rowid ,rowid 在整个数据库中是唯一的,rowid 确定了每条记录是在Oracle 中的哪一个数据文件、块、行上。

(2) 在重复的记录中,可能所有列的内容都相同,但rowid 不会相同,所以只要确定出重复记录中那些具有最大rowid 的就可以了,其余全部删除。

 

2.2    删除部分字段重复数据

2.2.1   重复记录全部删除

想要删除 部分 字段 重复的数据,可以使用下面语句进行删除 ,下面的语句是删除 表中字段1 和字段2 重复的数据 :

DELETE   FROM  表名 a

WHERE    ( 字段1 ,  字段2 )  

  IN   ( SELECT  字段1 , 字段2  

                FROM    表名

                GROUP    BY  字段1 ,

                         字段2

                HAVING   COUNT ( 1 )   >   1 )

;

上面的语句非常简单,就是将查询到的数据删除掉。不过这种删除执行的效率非常低,对于大数据量来说,可能会将数据库吊死。所以建议先将查询到的重复的数据插入到一个临时表中,然后进行删除,这样,执行删除的时候就不用再进行一次查询了。如下:

CREATE   TABLE  临时表  AS   ( select  字段1 , 字段2 , count (*)   from  表名  group   by  字段1 , 字段2  having   count (*)   >   1 ) ;

上面这句话就是建立了临时表,并将查询到的数据插入其中。下面就可以进行这样的删除操作了:

delete   from  表名 a  where  字段1 , 字段2  in   ( select  字段1,字段2  from  临时表 );

这种先建临时表再进行删除的操作要比直接用一条语句进行删除要高效得多。

例子:

   DELETE   FROM  tmp_lhr t

   WHERE    ( t.accesscode ,  t.lastserviceordercode ,  t.serviceinstancecode )   IN

          ( SELECT   a.accesscode ,  a.lastserviceordercode ,  a.serviceinstancecode 

           FROM    tmp_lhr a

           GROUP    BY  a.accesscode ,

                    a.lastserviceordercode ,

                    a.serviceinstancecode

           HAVING   COUNT ( 1 )   >   1 );

2.2.2   保留最新的一条记录

假如 想保留重复数据中最新的一条记录啊! 那怎么办呢? 在oracle 中,有个隐藏了自动rowid ,里面给每条记录一个唯一的rowid ,我们如果想保留最新的一条记录,我们就可以利用这个字段,保留重复数据中r o wid 最大的一条记录就可以了。

一、   如何查找重复记录?

SELECT   *

   FROM  TABLE_NAME  A

  WHERE   ROWID     NOT IN   ( SELECT   MAX ( ROWID )

                    FROM  TABLE_NAME D

                   WHERE   A .COL1  =  D.COL1

                     AND   A .COL2  =  D.COL2 );

二、   如何删除重复记录?   1、   方法1

DELETE   FROM  TABLE_NAME

WHERE   ROWID   NOT IN   ( SELECT   MAX ( ROWID )

                    FROM  TABLE_NAME D

                   group   by  d.col1 , d.col2 );

 

这种方法最简单!!!

2、   方法2

DELETE   FROM  TABLE_NAME  A

  WHERE   ROWID   NOT IN   ( SELECT   MAX ( ROWID )

                    FROM  TABLE_NAME D

                   WHERE   A .COL1  =  D.COL1

                     AND   A .COL2  =  D.COL2 );

3、   方法3  临时表

由此,我们要删除重复数据,只保留最新的一条数据,就可以这样写了:

create   table  临时表  as   select  a.字段1 , a.字段2 , MAX ( a.ROWID )  dataid  from  正式表 a  GROUP   BY  a.字段1 , a.字段2 ;

 

DELETE   FROM   正式 表 a

where  a.rowid  NOT IN   ( SELECT  b.dataid

                        FROM    临时表 b

                       WHERE   a.字段1  =  b.字段1

    and  a.字段2  =  b.字段2 );

commit ;

 

例子:

   DELETE   FROM  tmp_lhr t

   WHERE   t.rowid  not   in   ( SELECT   MAX ( ROWID )

                      FROM    tmp_lhr a

                      GROUP    BY  a.accesscode ,

                               a.lastserviceordercode ,

                               a.serviceinstancecode );

 

  DELETE   FROM  tmp_lhr t

  WHERE   t.rowid  !=

         ( SELECT   MAX ( ROWID )

          FROM    tmp_lhr a

          WHERE   a.accesscode  =  t.accesscode

          AND     a.lastserviceordercode  =  t.lastserviceordercode

          AND     a.serviceinstancecode  =  t.serviceinstancecode );

2.2.3   删除以某个字段为准的记录

  ----任意保留一条记录

DELETE   FROM  ods_entity_info_full_lhr_01 T

WHERE   T.ROWID  NOT   IN   ( SELECT   MAX ( A.ROWID )

                        FROM    ods_entity_info_full_lhr_01 A

                        GROUP    BY  entity_code ,

                                 entity_type );  

         ---保留 entity_id 最大的一条记录

         DELETE   FROM  ods_entity_info_full_lhr_01 a

         WHERE   a.rowid  NOT   IN

                ( SELECT  t.rowid

                 FROM    ods_entity_info_full_lhr_01 t

                 WHERE    ( t.entity_code ,  t.entity_type ,  t.entity_id )   IN

                        ( SELECT  entity_code ,

                               entity_type ,

                                MAX ( entity_id )

                         FROM    ods_entity_info_full_lhr_01

                         GROUP    BY  entity_code ,

                                  entity_type ));

2.3    删除完全重复记录

对于表中两行记录完全一样的情况,可以用下面 三种方式 获取到去掉重复数据后的记录:

1.   select   distinct   *   from  表名 ;

2.   select * from  表名  group by  列名 1, 列名 2,... having count(*)>1

3.   select * from   表名  a where rowid<(select max(rowid) from  表名  b where a. 列名 1=b. 列名 2 and ...)

2.3.1   方法 1

   DELETE   FROM  tmp_lhr t

   WHERE   t.rowid  not   in   ( SELECT   MAX ( ROWID )

                      FROM    tmp_lhr a

                      GROUP    BY  a.accesscode ,

                               a.lastserviceordercode ,

                               a.serviceinstancecode );

2.3.2   方法 2

可以将查询的记录放到临时表中,然后再将原来的表记录删除,最后将临时表的数据导回原来的表中。如下:

CREATE   TABLE  临时表  AS   ( select   distinct   *   from  表名 );

truncate   table  正式表 ;

insert   into  正式表  ( select   *   from  临时表 );

drop   table  临时表 ;

 

2.3.3   方法 3

DELETE   FROM  xr_maintainsite E

WHERE   E.ROWID  >   ( SELECT   MIN ( X.ROWID )

                   FROM    xr_maintainsite X

                   WHERE   X.Maintainid  =  E.Maintainid

                   AND     x.siteid  =  e.siteid ); -- 这里被更新表中所有字段都需要写全

 

2.4    采用row_number 分析函数取出重复的记录然后删除序号大于1 的记录

给出一个例子:

delete from aa where rowid in(select rid from(select rowid rid,row_number() over (partition by name order by id) as seq from aa) where seq>1);

3    测试案例

SYS@raclhr1> CREATE TABLE T_ROWS_LHR_20160809 AS SELECT * FROM SCOTT.EMP;

Table created.

SYS@raclhr1> INSERT INTO T_ROWS_LHR_20160809 SELECT * FROM T_ROWS_LHR_20160809;

14 rows created.

SYS@raclhr1> COMMIT;

Commit complete.

SYS@raclhr1> INSERT INTO T_ROWS_LHR_20160809 SELECT * FROM T_ROWS_LHR_20160809;

28 rows created.

SYS@raclhr1> COMMIT;

Commit complete.

SYS@raclhr1> SELECT COUNT(1) FROM T_ROWS_LHR_20160809;

  COUNT(1)

----------

        56

SYS@raclhr1> DELETE FROM T_ROWS_LHR_20160809

  2      WHERE ROWID NOT IN  (SELECT MAX(ROWID)

  3                        FROM T_ROWS_LHR_20160809 D

  4                       group by D.EMPNO,D.ENAME,D.JOB,D.MGR,D.DEPTNO);

42 rows deleted.

SYS@raclhr1> SELECT COUNT(1) FROM T_ROWS_LHR_20160809;

  COUNT(1)

----------

        14

SYS@raclhr1> COMMIT;

Commit complete.


本文名称:Oracle如何删除表中重复记录
网站链接:http://pwwzsj.com/article/iehpss.html