Oracle中查找和删除重复记录方法平时工作中可能会遇到当试图对库表中的某一列或几列创建唯一索引时,系统提示ORA-01452:不能创建唯一索引,发现重复记录。下面总结一下几种查找和删除重复记录的方法(以表CZ为例):表CZ的结构如下:SQLdescczNameNull?Type-----------------------------------------C1NUMBER(10)C10NUMBER(5)C20VARCHAR2(3)删除重复记录的方法原理:(1).在Oracle中,每一条记录都有一个rowid,rowid在整个数据库中是唯一的,rowid确定了每条记录是在Oracle中的哪一个数据文件、块、行上。(2).在重复的记录中,可能所有列的内容都相同,但rowid不会相同,所以只要确定出重复记录中那些具有最大rowid的就可以了,其余全部删除。重复记录判断的标准是:C1,C10和C20这三列的值都相同才算是重复记录。经查看表CZ总共有16条记录:SQLsetpagesize100SQLselect*fromcz;C1C10C20-----------------------12dsf12dsf12dsf12dsf23che12dsf12dsf12dsf12dsf23che23che23che23che34dff34dff34dff45err53dar61wee72zxc20rowsselected.1.查找重复记录的几种方法:(1).SQLselect*fromczgroupbyc1,c10,c20havingcount(*)1;C1C10C20-----------------------12dsf23che34dff(2).SQLselectdistinct*fromcz;C1C10C20-----------------------12dsf23che34dff(3).SQLselect*fromczawhererowid=(selectmax(rowid)fromczwherec1=a.c1andc10=a.c10andc20=a.c20);C1C10C20-----------------------12dsf23che34dff2.删除重复记录的几种方法:(1).适用于有大量重复记录的情况(在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);(2).适用于有少量重复记录的情况(注意,对于有大量重复记录的情况,用以下语句效率会很低):SQLdeletefromczawherea.rowid!=(selectmax(rowid)fromczbwherea.c1=b.c1anda.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);(3).适用于有少量重复记录的情况(临时表法):SQLcreatetabletestasselectdistinct*fromcz;(建一个临时表test用来存放重复的记录)SQLtruncatetablecz;(清空cz表的数据,但保留cz表的结构)SQLinsertintoczselect*fromtest;(再将临时表test里的内容反插回来)(4).适用于有大量重复记录的情况(Exceptioninto子句法):采用altertable命令中的Exceptioninto子句也可以确定出库表中重复的记录。这种方法稍微麻烦一些,为了使用“excepeioninto”子句,必须首先创建EXCEPTIONS表。创建该表的SQL脚本文件为utlexcpt.sql。对于win2000系统和UNIX系统,Oracle存放该文件的位置稍有不同,在win2000系统下,该脚本文件存放在$ORACLE_HOMEOra90rdbmsadmin目录下;而对于UNIX系统,该脚本文件存放在$ORACLE_HOME/rdbms/admin目录下。具体步骤如下:SQL@?/rdbms/admin/utlexcpt.sqlTablecreated.SQLdescexceptionsNameNull?Type-----------------------------------------ROW_IDROWIDOWNERVARCHAR2(30)TABLE_NAMEVARCHAR2(30)CONSTRAINTVARCHAR2(30)SQLaltertableczaddconstraintcz_uniqueunique(c1,c10,c20)exceptionsintoexceptions;*ERRORatline1:ORA-02299:cannotvalidate(TEST.CZ_UNIQUE)-duplicatekeysfoundSQLcreatetabledupsasselect*fromczwhererowidin(selectrow_idfromexceptions);Tablecreated.SQLselect*fromdups;C1C10C20-----------------------12dsf12dsf12dsf12dsf23che12dsf12dsf12dsf12dsf23che23che23che23che34dff34dff34dff16rowsselected.SQLselectrow_idfromexceptions;ROW_ID------------------AAAHD/AAIAAAADSAAAAAAHD/AAIAAAADSAABAAAHD/AAIAAAADSAACAAAHD/AAIAAAADSAAFAAAHD/AAIAAAADSAAHAAAHD/AAIAAAADSAAIAAAHD/AAIAAAADSAAGAAAHD/AAIAAAADSAADAAAHD/AAIAAAADSAAEAAAHD/AAIAAAADSAAJAAAHD/AAIAAAADSAAKAAAHD/AAIAAAADSAALAAAHD/AAIAAAADSAAMAAAHD/AAIAAAADSAANAAAHD/AAIAAAADSAAOAAAHD/AAIAAAADSAAP16rowsselected.SQLdeletefromczwhererowidin(selectrow_idfromexceptions);16rowsdeleted.SQLinsertintoczselectdistinct*fromdups;3rowscreated.SQLselect*fromcz;C1C10C20-----------------------12dsf23che34dff45err53dar61wee72zxc7rowsselected.从结果里可以看到重复记录已经删除。