Oracle如何删除表中重复记录

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,我们如果想保留最新的一条记录,我们就可以利用这个字段,保留重复数据中rowid最大的一条记录就可以了。

一、 如何查找重复记录?

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.

 

4   经验总结

重复数据删除技术可以提供更大的备份容量,实现更长时间的数据保留,还能实现备份数据的持续验证,提高数据恢复服务水平,方便实现数据容灾等。Oracle数据库重复数据删除技术有如下优势:更大的备份容量、数据能得到持续验证、有更高的数据恢复服务水平、方便实现备份数据的容灾。

通过摸索,相信你能发现更多更高效删除Oracle重复数据的方法。




About Me


...............................................................................................................................

● 本文作者:小麦苗,只专注于数据库的技术,更注重技术的运用

● 本文在itpub(http://blog.itpub.net/26736162)、博客园(http://www.cnblogs.com/lhrbest)和个人微信公众号(xiaomaimiaolhr)上有同步更新

● 本文itpub地址:http://blog.itpub.net/26736162/abstract/1/

● 本文博客园地址:http://www.cnblogs.com/lhrbest

● 本文pdf版及小麦苗云盘地址:http://blog.itpub.net/26736162/viewspace-1624453/

● 数据库笔试面试题库及解答:http://blog.itpub.net/26736162/viewspace-2134706/

● QQ群:230161599     微信群:私聊

● 联系我请加QQ好友(646634621),注明添加缘由

● 于 2017-07-01 09:00 ~ 2017-07-31 22:00 在魔都完成

● 文章内容来源于小麦苗的学习笔记,部分整理自网络,若有侵权或不当之处还请谅解

● 版权所有,欢迎分享本文,转载请保留出处

...............................................................................................................................

拿起手机使用微信客户端扫描下边的左边图片来关注小麦苗的微信公众号:xiaomaimiaolhr,扫描右边的二维码加入小麦苗的QQ群,学习最实用的数据库技术。

时间: 2024-10-26 04:29:24

Oracle如何删除表中重复记录的相关文章

如何删除表中重复记录?

问题描述 最近项目中遇到了一个需求,即"如何删除表中重复记录,使得所有重复的记录都只保留一行?".在Google了半个小时之后,发现居然没有一个是正常可用的,于是乎只好自己动手写了一个.因为即便是Grails提供了很好的GORM,但是使用SQL仍然不可能完全避免,因此把它共享出来.原文链接:http://www.groovyq.net/node/162 解决方案 解决方案二:你这是广告还是啥的???解决方案三:ding解决方案四:广而告之解决方案五:看了@@顶下解决方案六:帮顶下解决方

Oracle 查找与删除表中重复记录的步骤方法_oracle

这时候如果临时表中有重复数据,无论是主键字段businessid有重复,还是一整行有重复都会报出违反唯一主键约束错误. 方法:group by XX having count(*)>1,rowid,distinct,temporary table,procedure 1.查询表中的重复数据a.重复一个字段 b.重复多个字段 c.重复一整行 创建测试表: 复制代码 代码如下: create table cfa (businessid number,customer varchar2(50),bra

MySQL 删除表中重复记录

版本是:5.0.22-community-nt. 1. 为表folder新建一个临时表folder_tmp create table folder_tmp as select * from folder group by serverIp, userId, name, path; 这里根据serverIp, userId, name, path分组之后,表folder_tmp中留下的是主键id靠前的数据 2. 删除原来的表 drop table folder 3. 重命名表 alter tabl

如何查找、删除表中重复的记录

重复 如何查找.删除表中重复的记录软件环境: 1.Windows NT4.0+ORACLE 8.0.42.ORACLE安装路径为:C:\ORANT问题提出: 1.当我们想要为一个表创建唯一索引时,如果该表有重复的记录,则无法创建成功. 方法原理: 1.Oracle中,每一条记录都有一个rowid,rowid在整个数据库中是唯一的, rowid确定了每条记录是在ORACLE中的哪一个数据文件.块.行上. 2.在重复的记录中,可能所有列的内容都相同,但rowid不会相同,所以只要确定出重复记录中 那

python删除列表中重复记录的方法

  这篇文章主要介绍了python删除列表中重复记录的方法,涉及Python操作列表的相关技巧,需要的朋友可以参考下 ? 1 2 3 4 def removeListDuplicates(seq): seen = set() seen_add = seen.add return [ x for x in seq if x not in seen and not seen_add(x) ] 希望本文所述对大家的Python程序设计有所帮助.

确定Oracle数据库表中重复记录的方法

作为一个Oracle数据库开发者或者DBA,在实际工作中经常会遇到这样的问题:试图对库表中的某一列或几列创建唯一索引时,系统提示ORA-01452:不能创建唯一索引,发现重复记录. 下面我们以表code_ref为例来讨论这个问题及其解决办法. ERROR位于第1行: ORA-01452: 无法 CREATE UNIQUE INDEX:找到重复的关键字 Oracle系统提示不能对表code_ref创建一个唯一索引,因为系统发现表中存在重复的记录.我们必须首先找到表中的重复记录并删除该记录,才可以创

sql过滤、删除、表中重复记录语句

文章介绍利用having group by 及各种select in 联合查询来实现的多种不同方法的过滤重复记录的sql语名. - 1.查找表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断 代码如下 select * from people where peopleId in (select   peopleId  from   people  group  by   peopleId  having  count(peopleId) > 1) 2.删除表中多余的重复记录,重

高效快速删除Oracle表中重复记录

以前的一篇删除重复记录的虽然还不错 但是在我遇到重量级的大表时还是显的力不从心,不小心想到一种新的方法 思路1.保存不重复的记录 2.保存重复记录中的一个rowid //3.删除原表中rowid不为步骤2中rowid的记录 ,留下重复数据中的一条 3.找出记录中rowid为步骤2中rowid的记录 4 .1和3数据连接就是所要的数据了 具体操作例子 第一步:www.examw.com SQL> create table xxfgs_sig as (select imeid imeid,max(d

Sql Server里删除数据表中重复记录的例子_MsSql

[项目] 数据库中users表,包含u_name,u_pwd两个字段,其中u_name存在重复项,现在要实现把重复的项删除! [分析] 1.生成一张临时表new_users,表结构与users表一样: 2.对users表按id做一个循环,每从users表中读出一个条记录,判断new_users中是否存在有相同的u_name,如果没有,则把它插入新表:如果已经有了相同的项,则忽略此条记录: 3.把users表改为其它的名称,把new_users表改名为users,实现我们的需要. [程序] 复制代