在Oracle中利用Rowid查找和删除表中的重复记录.docx
平时工作中可能会遇到当试图对库表中的某一列或几列创建唯一索引时,系统提示
ORA-01452:不能创建唯一索引,发现重复记录。
下面总结一下几种查找和删除重复记录的方法(以表CZ为例):表CZ的结构如下:
SQLdescczNameNull?Type
C1NUMBER(10)C10NUMBER(5)C20VARCHAR2(3)
删除重复记录的方法原理:
在Oracle中,每一条记录都有一个rowid,rowid在整个数据库中是唯一的,rowid确定了每条记录是在Oracle中的哪一个数据文件、块、行上。
在重复的记录中,可能所有列的内容都相同,但rowid不会相同,所以只要确定出重复记录中那些具有最大rowid的就可以了,其余全部删除。
重复记录判断的标准是:
C1,C10和C20这三列的值都相同才算是重复记录。
经查看表CZ总共有16条记录:SQLsetpagesize100SQLselect*fromcz;
C1C10C20
12dsf
12dsf
12dsf
2dsf
3che
12dsf
12dsf
12dsf
2dsf
3che
23che
23che
3che
4dff
34dff
4dff
5err
3dar
1wee
2zxc
20rowsselected.
查找重复记录的几种方法:
(1).SQLselect*fromczgroupbyc1,c10,c20havingcount(*)1;C1C10C20
2dsf
3che
4dff
(2).SQLselectdistinct*fromcz;C1C10C20
2dsf
3che
4dff
(3).SQLselect*fromczawhererowid=(selectmax(rowid)fromczwherec1=a.c1andc10=a.c10andc20=a.c20);
C1C10C20
2dsf
3che
4dff
删除重复记录的几种方法:
适用于有大量重复记录的情况(在C1,C10和C20列上建有索引的时候,用以下语句效率会很高):
SQLdeleteczwhere(c1,c10,c20)in(selectc1,c10,c20fromczgroupbyc1,c10,c20havingcount(*)1)androwidnotin
(selectmin(rowid)fromczgroupbyc1,c10,c20havingcount(*)1);
SQLdeleteczwhererowidnotin(selectmin(rowid)fromczgroupbyc1,c10,c20);
适用于有少量重复记录的情况(注意,对于有大量重复记录的情况,用以下语句效率会很低):
SQLdeletefromczawherea.rowid!=(selectmax(rowid)fromczbwherea.c1=b.c1and
a.c10=b.c10anda.c20=b.c20);
SQLdeletefromczawherea.rowid(selectmax(rowid)fromczbwherea.c1=b.c1anda.c10=b.c10anda.c20=b.c20);
SQLdeletefromczawhererowid(selectmax(rowid)fromczwherec1=a.c1andc10=a.c10andc20=a.c20);
适用于有少量重复记录的情况(临时表法):
SQLcreatetabletestasselectdistinct*fromcz;(建一个临时表test用来存放重复的记录)
SQLtruncatetablecz;(清空cz表的数据,但保留cz表的结构)
SQLinsertintoczselect*fromtest;(再将临时表test里的内容反插回来)(4).适用于有大量重复记录的情况(Exceptioninto子句法):
采用altertable命令中的Exceptioninto子句也可以确定出库表中重复的记录。这种方法稍微麻烦一些,为了使用“excepeioninto”子句,必须首先创建EXCEPTIONS表。创建该表的SQL脚本文件为utlexcpt.sql。对于