在Oracle中如何利用Rowid查找和删除表中的重复记录

oracle|重复|重复记录

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

下面总结一下几种查找和删除重复记录的方法(以表CZ为例):
表CZ的结构如下:
SQL> desc cz
 Name                                      Null?    Type
 ----------------------------------------- -------- ------------------

 C1                                                 NUMBER(10)
 C10                                                NUMBER(5)
 C20                                                VARCHAR2(3)

删除重复记录的方法原理:
(1).在Oracle中,每一条记录都有一个rowid,rowid在整个数据库中是唯一的,rowid确定了每条记录是在Oracle中的哪一个数据文件、块、行上。

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

重复记录判断的标准是:
C1,C10和C20这三列的值都相同才算是重复记录。

经查看表CZ总共有16条记录:
SQL>set pagesize 100
SQL>select * from cz;

         C1        C10 C20
---------- ---------- ---
         1          2   dsf
         1          2   dsf
         1          2   dsf
         1          2   dsf
         2          3   che
         1          2   dsf
         1          2   dsf
         1          2   dsf
         1          2   dsf
         2          3   che
         2          3   che
         2          3   che
         2          3   che
         3          4   dff
         3          4   dff
         3          4   dff
         4          5   err
         5          3   dar
         6          1   wee
         7          2   zxc

20 rows selected.

1.查找重复记录的几种方法:
(1).SQL>select * from cz group by c1,c10,c20 having count(*) >1;
        C1        C10 C20
---------- ---------- ---
         1          2   dsf
         2          3   che
         3          4   dff

(2).SQL>select distinct * from cz;

        C1        C10 C20
---------- ---------- ---
         1          2   dsf
         2          3   che
         3          4   dff

(3).SQL>select * from cz a where rowid=(select max(rowid) from cz where c1=a.c1 and c10=a.c10 and c20=a.c20);
        C1        C10 C20
---------- ---------- ---
         1          2   dsf
         2          3   che
         3          4   dff

2.删除重复记录的几种方法:
(1).适用于有大量重复记录的情况(在C1,C10和C20列上建有索引的时候,用以下语句效率会很高):
SQL>delete cz where (c1,c10,c20) in (select c1,c10,c20 from cz group by c1,c10,c20 having count(*)>1) and rowid not in
(select min(rowid) from cz group by c1,c10,c20 having count(*)>1);

SQL>delete cz where rowid not in(select min(rowid) from cz group by c1,c10,c20);

(2).适用于有少量重复记录的情况(注意,对于有大量重复记录的情况,用以下语句效率会很低):
SQL>delete from cz a where a.rowid!=(select max(rowid) from cz b where a.c1=b.c1 and a.c10=b.c10 and a.c20=b.c20);

SQL>delete from cz a where a.rowid<(select max(rowid) from cz b where a.c1=b.c1 and a.c10=b.c10 and a.c20=b.c20);

SQL>delete from cz a where rowid <(select max(rowid) from cz  where c1=a.c1 and c10=a.c10 and c20=a.c20);

(3).适用于有少量重复记录的情况(临时表法):
SQL>create table test as select distinct * from cz; (建一个临时表test用来存放重复的记录)

SQL>truncate table cz;  (清空cz表的数据,但保留cz表的结构)

SQL>insert into cz select * from test;  (再将临时表test里的内容反插回来)

(4).适用于有大量重复记录的情况(Exception into 子句法):
采用alter table 命令中的 Exception into 子句也可以确定出库表中重复的记录。这种方法稍微麻烦一些,为了使用“excepeion into ”子句,必须首先创建 EXCEPTIONS 表。创建该表的 SQL 脚本文件为 utlexcpt.sql 。对于win2000系统和 UNIX 系统, Oracle 存放该文件的位置稍有不同,在win2000系统下,该脚本文件存放在$ORACLE_HOME\Ora90\rdbms\admin 目录下;而对于 UNIX 系统,该脚本文件存放在$ORACLE_HOME/rdbms/admin 目录下。

具体步骤如下:
SQL>@?/rdbms/admin/utlexcpt.sql

Table created.

SQL>desc exceptions
 Name                                      Null?    Type
 ----------------------------------------- -------- --------------

 ROW_ID                                             ROWID
 OWNER                                              VARCHAR2(30)
 TABLE_NAME                                 VARCHAR2(30)
 CONSTRAINT                                   VARCHAR2(30)

SQL>alter table cz add constraint  cz_unique unique(c1,c10,c20) exceptions into exceptions;  
                                                      *
ERROR at line 1:
ORA-02299: cannot validate (TEST.CZ_UNIQUE) - duplicate keys found

SQL>create table dups as select * from cz where rowid in (select row_id from exceptions);

Table created.

SQL>select * from dups;

        C1        C10 C20
---------- ---------- ---
         1          2   dsf
         1          2   dsf
         1          2   dsf
         1          2   dsf
         2          3   che
         1          2   dsf
         1          2   dsf
         1          2   dsf
         1          2   dsf
         2          3   che
         2          3   che
         2          3   che
         2          3   che
         3          4   dff
         3          4   dff
         3          4   dff

16 rows selected.

SQL>select row_id from exceptions;

ROW_ID
------------------
AAAHD/AAIAAAADSAAA
AAAHD/AAIAAAADSAAB
AAAHD/AAIAAAADSAAC
AAAHD/AAIAAAADSAAF
AAAHD/AAIAAAADSAAH
AAAHD/AAIAAAADSAAI
AAAHD/AAIAAAADSAAG
AAAHD/AAIAAAADSAAD
AAAHD/AAIAAAADSAAE
AAAHD/AAIAAAADSAAJ
AAAHD/AAIAAAADSAAK
AAAHD/AAIAAAADSAAL
AAAHD/AAIAAAADSAAM
AAAHD/AAIAAAADSAAN
AAAHD/AAIAAAADSAAO
AAAHD/AAIAAAADSAAP

16 rows selected.

SQL>delete from cz where rowid in ( select row_id from exceptions);

16 rows deleted.

SQL>insert into cz select distinct * from dups;

3 rows created.

SQL>select *from cz;
 
        C1        C10 C20
---------- ---------- ---
         1          2   dsf
         2          3   che
         3          4   dff
         4          5   err
         5          3   dar
         6          1   wee
         7          2   zxc

7 rows selected.

从结果里可以看到重复记录已经删除。

时间: 2024-09-20 20:47:34

在Oracle中如何利用Rowid查找和删除表中的重复记录的相关文章

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

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

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

《Oracle SQL疑难解析》——1.10 删除表中的所有行

1.10 删除表中的所有行 Oracle SQL疑难解析 1.10.1 要解决的问题 从指定的表中删除所有数据. 1.10.2 解决方法 如果用DELETE语句来删除所有行,则Oracle会完整地把删除行为记入日志,以便如果是误操作,我们还有机会将数据回滚.但正是因为要记日志,所以需要花一定的时间,有时达不到我们希望的速度. 作为补充,Oracle提供了一个TRUNCATE(截断)语句来删除表中的所有数据.可以用下面的语句来截断HR.EMPLOYEES表: truncate table hr.e

Oracle如何删除表中重复记录

Oracle如何删除表中重复记录 1  引言 在对数据库进行操作过程中我们可能会遇到这种情况,表中的数据可能重复出现,使我们对数据库的操作过程中带来读诸多不便,那么怎么删除这些重复没有用的数据呢? 平时工作中可能会遇到当试图对库表中的某一列或几列创建唯一索引时,系统提示 ORA-01452 :不能创建唯一索引,发现重复记录. 2  处理过程 重复的数据可能有这样两种情况:第一种是表中只有某些字段一样,第二种是两行记录完全一样.删除重复记录后的结果也分为2种,第一种是重复的记录全部删除,第二种是重

Oracle 查询与删除表中的重复记录sql语句

方法:  代码如下 复制代码 group by  XX having count(*)>1,rowid,distinct,temporary table,procedure 下面语句可以查询出那些数据是重复的:  代码如下 复制代码 select 字段1,字段2,count(*) from 表名 group by 字段1,字段2 having count(*) > 1 将上面的>号改为=号就可以查询出没有重复的数据了. 想要删除这些重复的数据,可以使用下面语句进行删除  代码如下 复制代

单链表-@数据结构大神:查找并删除循环链表中的元素。85行的打印。为啥错了,求解

问题描述 @数据结构大神:查找并删除循环链表中的元素.85行的打印.为啥错了,求解 //循环单链表删除KEY.c:是否在.在首.唯一一个.在尾 # include<stdio.h> # include<stdlib.h> # include<malloc.h> # define array_size 50 typedef struct Node{ char data; struct Node *next; }Node,*Linklist; int i,len,key,a

SQL Server查找与删除表重复记录sql语句

在该示例中,我们将使用下表,它具有重复的 PK 值.在该表中,主键是两列(col1.col2).我们无法创建唯一索引或主键约束,因为这两行具有重复的 PK.该过程演示如何识别和删除重复的主键.    代码如下 复制代码 create table t1(col1 int, col2 int, col3 char(50)) insert into t1 values (1, 1, 'data value one') insert into t1 values (1, 1, 'data value o

怎样删除表中的重复数据,谢谢大家

问题描述 怎样删除表中的重复数据,谢谢大家 表内容如下: id fwbm kjbh sfxm dj yl ....................... 52578 d01142 d011422015928 001 .400 0 54.70 54.70 0 0 2015-09-28 00:00:00.000 NULL 52579 d01142 d011422015928 040 2.990 2 5.98 5.98 0 0 2015-09-28 00:00:00.000 NULL 52580 d0

如何删除表中重复记录?

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