Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【DB笔试面试469】Oracle中如何删除表中重复的记录?

【DB笔试面试469】Oracle中如何删除表中重复的记录?

作者头像
AiDBA宝典
发布于 2019-09-30 08:53:33
发布于 2019-09-30 08:53:33
2.9K00
代码可运行
举报
运行总次数:0
代码可运行

题目部分

Oracle中如何删除表中重复的记录?

答案部分

平时工作中可能会遇到这种情况,当试图对表中的某一列或几列创建唯一索引时,系统提示ORA-01452 :不能创建唯一索引,发现重复记录。这个时候只能创建普通索引或者删除重复记录后再创建唯一索引。

重复的数据可能有这样两种情况:第一种是表中只有某些字段一样,第二种是两行记录完全一样。删除重复记录后的结果也分为两种,第一种是重复的记录全部删除,第二种是重复的记录中只保留最新的一条记录,在一般业务中,第二种的情况较多。

1、删除重复记录的方法原理

在Oracle中,每一条记录都有一个ROWID,ROWID在整个数据库中是唯一的,ROWID确定了每条记录是在Oracle中的哪一个数据文件、块、行上。在重复的记录中,可能所有列上的内容都相同,但ROWID不会相同,所以,只要确定出重复记录中那些具有最大ROWID的就可以了,其余全部删除。

2、删除重复记录的方法

若想要删除部分字段重复的数据,则使用下面语句进行删除,下面的语句是删除表中字段1和字段2重复的数据:

DELETE FROM 表名

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 临时表);

假如想保留重复数据中最新的一条记录,应该怎么做呢?可以利用ROWID,保留重复数据中ROWID最大的一条记录即可,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
DELETE FROM TABLE_NAME WHERE ROWID NOT IN (SELECT MAX(ROWID)  FROM TABLE_NAME D GROUP BY D.COL1,D.COL2);

下面给出一个示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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.

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

& 说明:

有关删除重复数据更多的内容可以参考我的BLOG:http://blog.itpub.net/26736162/viewspace-2123234/

本文选自《Oracle程序员面试笔试宝典》,作者:李华荣。

About Me:小麦苗

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

● 作者博客地址:http://blog.itpub.net/26736162/abstract/1/

● 本系列题目来源于作者的学习笔记,部分整理自网络,若有侵权或不当之处还请谅解

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

● 题目解答若有不当之处,还望各位朋友批评指正,共同进步

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-12-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DB宝 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【DB笔试面试666】在Oracle中,高并发高负载情况下,如何给表添加字段、设置DEFAULT值
在Oracle中,在高并发、高负载的情况下,如何给表添加字段并设置DEFAULT值?
AiDBA宝典
2019/10/25
3.7K0
oracle中如何删除重复数据
        我们可能会出现这种情况,某个表原来设计不周全,导致表里面的数据数据重复,那么,如何对重复的数据进行删除呢?         重复的数据可能有这样两种情况,第一种时表中只有某些字段一样,第二种是两行记录完全一样。 一、对于部分字段重复数据的删除         先来谈谈如何查询重复的数据吧。         下面语句可以查询出那些数据是重复的:   select 字段1,字段2,count(*) from 表名 group by 字段1,字段2 having count(*) > 1         将上面的>号改为=号就可以查询出没有重复的数据了。         想要删除这些重复的数据,可以使用下面语句进行删除   delete from 表名 a where 字段1,字段2 in     (select 字段1,字段2,count(*) from 表名 group by 字段1,字段2 having count(*) > 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 临时表);         这种先建临时表再进行删除的操作要比直接用一条语句进行删除要高效得多。        这个时候,大家可能会跳出来说,什么?你叫我们执行这种语句,那不是把所有重复的全都删除吗?而我们想保留重复数据中最新的一条记录啊!大家不要急,下面我就讲一下如何进行这种操作。        在oracle中,有个隐藏了自动rowid,里面给每条记录一个唯一的rowid,我们如果想保留最新的一条记录, 我们就可以利用这个字段,保留重复数据中rowid最大的一条记录就可以了。        下面是查询重复数据的一个例子:   select a.rowid,a.* from 表名 a  where a.rowid !=  (   select max(b.rowid) from 表名 b   where a.字段1 = b.字段1 and   a.字段2 = b.字段2  )        下面我就来讲解一下,上面括号中的语句是查询出重复数据中rowid最大的一条记录。        而外面就是查询出除了rowid最大之外的其他重复的数据了。        由此,我们要删除重复数据,只保留最新的一条数据,就可以这样写了:  delete from 表名 a  where a.rowid !=  (   select max(b.rowid) from 表名 b   where a.字段1 = b.字段1 and   a.字段2 = b.字段2  )        随便说一下,上面语句的执行效率是很低的,可以考虑建立临时表,讲需要判断重复的字段、rowid插入临时表中,然后删除的时候在进行比较。   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 !=  (   select b.dataid from 临时表 b   where a.字段1 = b.字段1 and   a.字段2 = b.字段2  );  commit; 二、对于完全重复记录的删除         对于表中两行记录完全一样的情况,可以用下面语句获取到去掉重复数据后的记录:   select distinct * from 表名   可以将查询的记录放到临时表中,然后再将原来的表记录删除,最后将临时表的数据导回原来的表中。如下:   CREATE TABLE 临时表 AS (select distinct * from 表名);   truncate table 正式表;            --注:原先由于笔误写成了drop table 正式表;,现在已经改正过来   insert into 正式表 (select * from 临时表);   drop table 临时表;
源哥
2018/08/28
2.5K0
【DB笔试面试664】在Oracle中,模拟死锁产生的一个场景。
Oracle中的死锁比较复杂,产生死锁的原因也有很多种,曾经有面试官让面试人员口头模拟死锁产生的一个场景。
AiDBA宝典
2019/10/23
7180
【DB笔试面试664】在Oracle中,模拟死锁产生的一个场景。
【DB笔试面试631】在Oracle中,什么是动态采样(Dynamic Sampling)?
对于没有收集统计信息的表,Oracle为了能够得到相对准确的执行计划,会在执行SQL之前对SQL语句涉及到的表做动态采样(Dynamic Sampling,从Oracle 11.2.0.4开始称之为Dynamic Statistic)。
AiDBA宝典
2019/09/29
6200
【DB笔试面试631】在Oracle中,什么是动态采样(Dynamic Sampling)?
【DB笔试面试517】在Oracle中,什么是临时表?它有哪些分类?有关临时表需要注意什么?
目前所有使用Oracle作为数据库支撑平台的应用,大部分是数据量比较庞大的系统,即表的数据量级一般情况下都是在百万级以上。当然,在Oracle中创建分区是一种不错的选择,但是当发现应用有多张表关联的时候,并且这些表大部分都比较庞大,而关联的时候发现其中的某一张或者某几张表关联之后得到的结果集非常小,并且查询得到这个结果集的速度非常快,那么这个时候考虑在Oracle中创建“临时表”。
AiDBA宝典
2019/09/29
1.3K0
【DB笔试面试650】在Oracle中,如何查询表的DML操作数据变化量?
DBA_TAB_MODIFICATIONS视图(基表为SYS.MON_MODS_ALL$)记录了从上次收集统计信息以来表中DML操作变化的数据量,包括执行INSERT、UPDATE和DELETE影响的行数,以及是否执行过TRUNCATE操作。另外,DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO可以将内存(SGA)中的数据快速刷新到数据字典SYS.MON_MODS_ALL$中。
AiDBA宝典
2019/09/29
2.3K0
【DB笔试面试650】在Oracle中,如何查询表的DML操作数据变化量?
【DB笔试面试474】普通表转换为分区表有哪些办法?
(2)子查询插入方法(Insert With a Subquery Method)
AiDBA宝典
2019/09/30
7060
【DB笔试面试593】在Oracle中,表的访问方式有哪几种?
访问表的方式也叫优化器访问路径,主要有3种访问路径:全表扫描(FULL TABLE SCAN,FTS)、索引扫描(INDEX SCAN)和ROWID访问。
AiDBA宝典
2019/09/29
1.2K0
【DB笔试面试593】在Oracle中,表的访问方式有哪几种?
sql DISTINCT去掉重复的数据统计方法
sql DISTINCT去掉重复的数据统计方法(2009-01-13 15:05:43)转载 标签:sqldistinct杂谈 分类:sql
零式的天空
2022/03/21
2.9K0
104-oracle大表删除重复记录的几种方法
如果是小表,随便怎么折腾都行; 如果是大表(至少1千万条记录以上,或者占用10G以上空间), 我们可能需要想办法加快这个速度 , 这时可以参考下面方法:
老虎刘
2023/09/01
7570
104-oracle大表删除重复记录的几种方法
【DB笔试面试812】在Oracle中,什么是闪回表(Flashback TABLE)?
闪回表(Flashback TABLE)是将表恢复到过去的某个时间点或某个SCN值时的状态。对闪回表语句不能进行回滚,如果要闪回表,那么需要有对表的FLASHBACK对象权限或者FLASHBACK ANY TABLE系统权限。
AiDBA宝典
2020/06/04
5530
【DB笔试面试438】如何正确的删除表空间数据文件?
ALTER TABLESPACE TS_DD_LHR DROP DATAFILE n; --n为数据文件号
AiDBA宝典
2019/09/30
1.9K0
【DB笔试面试498】当DML语句中有一条数据报错时,如何让该DML语句继续执行?
当一个DML语句运行的时候,如果遇到了错误,那么这条语句会进行回滚,就好像没有执行过。对于一个大的DML语句而言,如果个别数据错误而导致整个语句的回滚,那么会浪费很多的资源和运行时间。所以,从Oracle 10g开始Oracle支持记录DML语句的错误,而允许语句自动继续执行。这个功能可以使用DBMS_ERRLOG包实现。
AiDBA宝典
2019/09/30
9200
【DB笔试面试498】当DML语句中有一条数据报错时,如何让该DML语句继续执行?
【DB笔试面试594】在Oracle中,关键字NOLOGGING、APPEND和PARALLEL提高DML性能方面有什么差别?
在Oracle中,关键字NOLOGGING、APPEND和PARALLEL提高DML性能方面有什么差别?
AiDBA宝典
2019/09/29
1.7K0
【DB笔试面试598】在Oracle中,如何得到真实的执行计划?
在Oracle数据库中判断得到的执行计划是否准确,就是看目标SQL是否被真正执行过,真正执行过的SQL所对应的执行计划就是准确的,反之则有可能不准,因此,通过10046事件及如下的几种方式得到的执行计划是最准确的,而从其它方式获取到的执行计划都有可能不准确。
AiDBA宝典
2019/09/29
7310
[Oracle-> MySQL] Oracle通过dblink连接MySQL--Oracle 19c连接到MySQL 5.7
今天小麦苗给大家分享的是[Oracle-> MySQL] Oracle通过dblink连接MySQL--Oracle 19c pdb连接到MySQL 5.7。
AiDBA宝典
2019/09/29
3.3K0
[Oracle-> MySQL] Oracle通过dblink连接MySQL--Oracle 19c连接到MySQL 5.7
【DB笔试面试791】在Oracle中,BBED模拟修复坏块。
● 作者博客地址:http://blog.itpub.net/26736162/abstract/1/
AiDBA宝典
2020/05/07
5900
【DB笔试面试637】在Oracle中,直方图使用示例。
列SAL上只有最大值,最小值两条记录分别对应端点号(ENDPOINT_NUMBER)0和1,这种显示说明列SAL没有直方图信息,从DBA_TAB_COL_STATISTICS的HISTOGRAM列值为NONE也说明列SAL没有直方图。
AiDBA宝典
2019/09/29
1.3K0
【DB笔试面试550】在Oracle中,函数索引是什么?
在Oracle中,有一类特殊的索引,称为函数索引(Function-Based Indexes,FBI),它基于对表中列进行计算后的结果创建索引。函数索引在不修改应用程序的逻辑基础上提高了查询性能。如果没有函数索引,那么任何在列上执行了函数的查询都不能使用这个列的索引。当在查询中包含该函数时,数据库才会使用该函数索引。函数索引可以是一个B-Tree索引或位图索引。
AiDBA宝典
2019/09/29
1.6K0
【DB笔试面试553】在Oracle中,什么是不可见索引?
索引维护是DBA的一项重要工作。当一个系统运行很长一段时间,经过需求变更、结构设计变化后,系统中就可能会存在一些不再被使用的索引,或者使用效率很低的索引。这些索引的存在,不仅占用系统空间,而且会降低事务效率,增加系统的负载。因此,需要找出那些无用或低效的索引,并删除它们(找出无用索引可以通过索引监控的方法)。但是,直接删除索引还是存在一定风险的。例如,某些索引可能只是在一些周期的作业中被使用到,而如果监控周期没有覆盖到这些作业的触发点,那么就会认为索引是无用的,从而将其删除。当作业启动后,可能就会对系统性能造成冲击。这时,可能就会手忙脚乱地去找回索引定义语句、重建索引。在Oracle 11g里,Oracle提供了一个新的特性来降低直接删除索引或者禁用索引的风险,那就是不可见索引(Invisible Indexes)。
AiDBA宝典
2019/09/29
6780
推荐阅读
【DB笔试面试666】在Oracle中,高并发高负载情况下,如何给表添加字段、设置DEFAULT值
3.7K0
oracle中如何删除重复数据
2.5K0
【DB笔试面试664】在Oracle中,模拟死锁产生的一个场景。
7180
【DB笔试面试631】在Oracle中,什么是动态采样(Dynamic Sampling)?
6200
【DB笔试面试517】在Oracle中,什么是临时表?它有哪些分类?有关临时表需要注意什么?
1.3K0
【DB笔试面试650】在Oracle中,如何查询表的DML操作数据变化量?
2.3K0
【DB笔试面试474】普通表转换为分区表有哪些办法?
7060
【DB笔试面试593】在Oracle中,表的访问方式有哪几种?
1.2K0
sql DISTINCT去掉重复的数据统计方法
2.9K0
104-oracle大表删除重复记录的几种方法
7570
【DB笔试面试812】在Oracle中,什么是闪回表(Flashback TABLE)?
5530
【DB笔试面试438】如何正确的删除表空间数据文件?
1.9K0
【DB笔试面试498】当DML语句中有一条数据报错时,如何让该DML语句继续执行?
9200
【DB笔试面试594】在Oracle中,关键字NOLOGGING、APPEND和PARALLEL提高DML性能方面有什么差别?
1.7K0
【DB笔试面试598】在Oracle中,如何得到真实的执行计划?
7310
[Oracle-> MySQL] Oracle通过dblink连接MySQL--Oracle 19c连接到MySQL 5.7
3.3K0
【DB笔试面试791】在Oracle中,BBED模拟修复坏块。
5900
【DB笔试面试637】在Oracle中,直方图使用示例。
1.3K0
【DB笔试面试550】在Oracle中,函数索引是什么?
1.6K0
【DB笔试面试553】在Oracle中,什么是不可见索引?
6780
相关推荐
【DB笔试面试666】在Oracle中,高并发高负载情况下,如何给表添加字段、设置DEFAULT值
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验