`
jake0719
  • 浏览: 88915 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Oracle中查找和删除重复记录方法简介

阅读更多

收藏的共享下,蛮不错的.

 

作者:bensiyuan

转自http://tech.ccidnet.com/art/1107/20070403/1051589_1.html

 

平时工作中可能会遇到当试图对库表中的某一列或几列创建唯一索引时,系统提示 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_HOMEOra90rdbmsadmin 目录下;而对于 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.

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

分享到:
评论
1 楼 aaron2007 2008-12-26  
晕乎乎的
不过确实挺全的!记得面试的时候我还被问道这个呢!呵呵当时没有做出来!就知道distinct呵呵

相关推荐

    Oracle中查找和删除重复记录方法

    在重复的记录中,可能所有列的内容都相同,但rowid不会相同,所以只要确定出重复记录中那些具有最大rowid的就可以了,其余全部删除。重复记录判断的标准是:C1,C10和C20这三列的值都相同才算是重复记录。

    Oracle 查找与删除表中重复记录的步

    Oracle 查找与删除表中重复记录的步Oracle 查找与删除表中重复记录的步

    Oracle中用Rowid查找和删除表中的重复记录

    总结一下几种查找和删除重复记录的方法,适用于有大量重复记录的情况

    解决Oracle删除重复数据只留一条的方法详解

    查询及删除重复记录的SQL语句1、查找表中多余的重复记录,重复记录是根据单个字段(Id)来判断select * from 表 where Id in (select Id from 表 group by Id having count(Id) &gt; 1)2、删除表中多余的重复记录,...

    ORACLE重复记录查询.docxORACLE

    1、查找表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断 select * from people where peopleId in (select peopleId from people group by peopleId having count (peopleId) &gt; 1) 2、删除表中多余...

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

    这时候如果临时表中有重复数据,无论是主键字段businessid有重复,还是一整行有重复都会报出违反唯一主键约束错误。 方法:group by XX having count(*)&gt;1,rowid,distinct,temporary table,procedure 1、查询表中的...

    解析Oracle查询和删除JOB的SQL

    查询及删除重复记录的SQL语句1、查找表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断select * from peoplewhere peopleId in (select peopleId from people group by peopleId having count...

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 连接字符串

     删除“开始”/“程序”中所有Oracle的组和图标。  删除所有与Oracle相关的目录,包括: C:\Program file\Oracle目录。 ORACLE_BASE目录。 C:\Documents and Settings\系统用户名、LocalSettings\Temp目录下的...

    oracle10g课堂练习I(2)

    Oracle 产品和服务 1-5 Oracle Database 10 g :“g”代表网格 1-6 Oracle 数据库体系结构 1-8 数据库结构 1-9 Oracle 内存结构 1-10 进程结构 1-12 Oracle 实例管理 1-13 服务器进程和数据库缓冲区高速缓存 ...

    ORACLE之常用FAQ V1.0(整理)

    [Q]怎么样抽取重复记录 5 [Q]怎么样设置自治事务 5 [Q]怎么样在过程中暂停指定时间 5 [Q]怎么样快速计算事务的时间与日志量 5 [Q]怎样创建临时表 6 [Q]怎么样在PL/SQL中执行DDL语句 6 [Q]怎么样获取IP地址 7 [Q]怎么...

    Oracle事例

    当指定时,如果父表中的记录被删除,则依赖于父表的记录也被删除 REFERENCE 表名() on delete cascade; 7、删除带约束的表 Drop table 表名 cascade constraints; 8:索引管理 &lt;1&gt;.creating function-based...

    【最新版】navicat150_premium_en.dmg navicat-premium: 15.0.14【亲测可用】最好的MySQL数据库开发工具

    使用我们的内置编辑器添加,修改和删除记录,您可以在Tree View,JSON View和类似电子表格的经典Grid View中方便地进行编辑。Navicat为您提供有效管理数据并确保流程平稳所需的工具。 Visual SQL / Query Builder将...

    orcale常用命令

    下面按类别列出一些ORACLE用户常用数据字典的查询使用方法。 1、用户 查看当前用户的缺省表空间 SQL&gt;select username,default_tablespace from user_users; 查看当前用户的角色 SQL&gt;select * from user_...

    PHP开发实战1200例(第1卷).(清华出版.潘凯华.刘中华).part1

    实例129 去除数组中的重复元素 158 实例130 字符串与数组的转换 159 实例131 对数组元素进行随机排序 160 实例132 随机抽取数组中元素 161 实例133 二维数组的输出 162 实例134 获取数组当前的键名和值 162 实例135 ...

    PHP开发实战1200例(第1卷).(清华出版.潘凯华.刘中华).part2

    实例129 去除数组中的重复元素 158 实例130 字符串与数组的转换 159 实例131 对数组元素进行随机排序 160 实例132 随机抽取数组中元素 161 实例133 二维数组的输出 162 实例134 获取数组当前的键名和值 162 实例135 ...

    程序员的SQL金典6-8

     10.2.3 全表扫描和索引查找  10.2.4 优化手法  10.3 事务  10.3.1 事务简介  10.3.2 事务的隔离  10.3.3 事务的隔离级别  10.3.4 事务的使用  10.4 自动增长字段  10.4.1 MySQL中的自动增长字段  10.4.2 ...

    程序员的SQL金典7-8

     10.2.3 全表扫描和索引查找  10.2.4 优化手法  10.3 事务  10.3.1 事务简介  10.3.2 事务的隔离  10.3.3 事务的隔离级别  10.3.4 事务的使用  10.4 自动增长字段  10.4.1 MySQL中的自动增长字段  10.4.2 ...

    程序员的SQL金典3-8

     10.2.3 全表扫描和索引查找  10.2.4 优化手法  10.3 事务  10.3.1 事务简介  10.3.2 事务的隔离  10.3.3 事务的隔离级别  10.3.4 事务的使用  10.4 自动增长字段  10.4.1 MySQL中的自动增长字段  10.4.2 ...

Global site tag (gtag.js) - Google Analytics