关于操作失误的数据修复

简介: 在系统升级的过程中,准备了大量的脚本,分成几个窗口来分别执行。 在碰到问题的时候,一定要很细心和冷静,不经意的错误可以需要几倍,几十倍的努力来挽回。 准生产环境中有一个表。
在系统升级的过程中,准备了大量的脚本,分成几个窗口来分别执行。
在碰到问题的时候,一定要很细心和冷静,不经意的错误可以需要几倍,几十倍的努力来挽回。
准生产环境中有一个表。TREATMENT_ACTIVITY,现在需要从另外一个临时的schema中insert一部分数据。

 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 ENTITY_KEY                                NOT NULL NUMBER(4)
 ENTITY_ID                                 NOT NULL NUMBER(9)
 ENTITY_TYPE                               NOT NULL VARCHAR2(10)
 ACTIVITY_CODE                             NOT NULL VARCHAR2(25)
 ACTIVITY_DATE                             NOT NULL TIMESTAMP(6)
 SYS_CREATION_DATE                         NOT NULL DATE
 SYS_UPDATE_DATE                                    DATE
 OPERATOR_ID                                        NUMBER(9)
 APPLICATION_ID                                     CHAR(6)
 DL_SERVICE_CODE                                    CHAR(5)
 DL_UPDATE_STAMP                                    NUMBER(4)
 APPROVAL_INDICATOR                                 CHAR(1)
 MEMO_ID                                   NOT NULL VARCHAR2(100)
 REASON_CODE                               NOT NULL VARCHAR2(6)
 STEP_ID                                            VARCHAR2(31)
 POLICY_CODE                                        VARCHAR2(128)
 PA_IND                                             CHAR(1)

值得一提的是,这个表没有主键,只创建了一些相关的索引,但是执行的时候发现数据有很大的偏差。
插入数据前,有500多万,需要插入数据400多万,预计数据应该是1千万,但是实际却是1千五百万。
Initial data of this on before import : 5747945
Data imported from temp schema: 4662877
so we expected to see : 10410822
But the count of this table after imported is 15073699

最后经过测试发现,是在使用Nohup执行一个批量脚本后,发现有一个表执行的很慢,就手动kill掉了session.手工插入,结果这个插入操作还在后台运行,结果手工又执行了一遍,因为没有主键,所以没有发现任何异常,做最后的数据统计的时候才发现。
找到了问题的原因,想把多余的数据删除。
首先尝试使用如下的方式来查看数据条数。但是竟然给我返回了0条数据。
SQL> select count(*) from TREATMENT_ACTIVITY where (
 ENTITY_KEY                ,            
 ENTITY_ID                ,            
 ENTITY_TYPE              ,            
 ACTIVITY_CODE            ,            
 ACTIVITY_DATE            ,            
 SYS_CREATION_DATE        ,            
 SYS_UPDATE_DATE          ,            
 OPERATOR_ID              ,            
 APPLICATION_ID           ,            
 DL_SERVICE_CODE          ,            
 DL_UPDATE_STAMP          ,            
 APPROVAL_INDICATOR       ,            
 MEMO_ID                  ,            
 REASON_CODE              ,            
 STEP_ID                  ,            
 POLICY_CODE              ,            
 PA_IND   ) in (select 
 19   ENTITY_KEY                ,            
 ENTITY_ID                ,            
 ENTITY_TYPE              ,            
 ACTIVITY_CODE            ,            
 ACTIVITY_DATE            ,            
 SYS_CREATION_DATE        ,            
 SYS_UPDATE_DATE          ,            
 OPERATOR_ID              ,            
 APPLICATION_ID           ,            
 DL_SERVICE_CODE          ,            
 DL_UPDATE_STAMP          ,            
 APPROVAL_INDICATOR       ,            
 MEMO_ID                  ,            
 REASON_CODE              ,            
 STEP_ID                  ,            
 POLICY_CODE              ,            
 PA_IND   from mig_tmp.TREATMENT_ACTIVITY_ext)  
   /

  COUNT(*)
----------
         0

我是明明知道数据有重复,但是查看却匹配不出来。那使用rowid来做一把测试。
select count(*)  from  dr_TREATMENT_ACTIVITY t1 where  t1.rowid != (select max(rowid) from dr_TREATMENT_ACTIVITY t2  
where t1.ENTITY_KEY          = t2.ENTITY_KEY                    
 and t1.ENTITY_ID           = t2.ENTITY_ID                     
 and t1.ENTITY_TYPE         = t2.ENTITY_TYPE                   
 and t1.ACTIVITY_CODE       = t2.ACTIVITY_CODE                 
 and t1.ACTIVITY_DATE       = t2.ACTIVITY_DATE                 
 and t1.SYS_CREATION_DATE   = t2.SYS_CREATION_DATE             
 and t1.SYS_UPDATE_DATE     = t2.SYS_UPDATE_DATE               
 and t1.OPERATOR_ID         = t2.OPERATOR_ID                   
 and t1.APPLICATION_ID      = t2.APPLICATION_ID                
 and t1.DL_SERVICE_CODE     = t2.DL_SERVICE_CODE               
 and t1.DL_UPDATE_STAMP     = t2.DL_UPDATE_STAMP               
 and t1.APPROVAL_INDICATOR  = t2.APPROVAL_INDICATOR            
 and t1.MEMO_ID             = t2.MEMO_ID                       
 and t1.REASON_CODE         = t2.REASON_CODE                   
 and t1.STEP_ID             = t2.STEP_ID                       
 and t1.POLICY_CODE         = t2.POLICY_CODE                   
 and t1.PA_IND              = t2.PA_IND ) 


  COUNT(*)
----------
         0

最后灵机一动,拼成一个字符串来。         
SQL> select count(*) from TREATMENT_ACTIVITY where (
  2   ENTITY_KEY               ||            
  3   ENTITY_ID                ||         
 ENTITY_TYPE              ||         
 ACTIVITY_CODE            ||         
 ACTIVITY_DATE            ||         
 SYS_CREATION_DATE        ||         
 SYS_UPDATE_DATE          ||         
 OPERATOR_ID              ||         
 APPLICATION_ID           ||         
 DL_SERVICE_CODE          ||         
 DL_UPDATE_STAMP          ||         
 APPROVAL_INDICATOR       ||         
 MEMO_ID                  ||         
 REASON_CODE              ||         
 STEP_ID                  ||         
 POLICY_CODE         ||                
  4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   PA_IND   ) in (select 
 19   ENTITY_KEY              ||            
 ENTITY_ID               ||            
 ENTITY_TYPE             ||            
 ACTIVITY_CODE           ||            
 ACTIVITY_DATE           ||            
 SYS_CREATION_DATE       ||            
 SYS_UPDATE_DATE         ||            
 OPERATOR_ID             ||            
 APPLICATION_ID          ||            
 DL_SERVICE_CODE         ||            
 DL_UPDATE_STAMP         ||            
 APPROVAL_INDICATOR      ||            
 MEMO_ID                 ||            
 REASON_CODE             ||            
 20   21   22   23   24   25   26   27   28   29   30   31   32   33   STEP_ID                 ||            
 34   POLICY_CODE              ||           
 PA_IND   from mig_tmp.TREATMENT_ACTIVITY_ext) 35  
 36  /

  COUNT(*)
----------
   9325754
Elapsed: 00:01:41.22        

这样就可以直接使用delete来先删除重复插入的数据。然后重新插入。
delete from TREATMENT_ACTIVITY where (
 ENTITY_KEY               ||            
 ENTITY_ID                ||         
 ENTITY_TYPE              ||         
 ACTIVITY_CODE            ||         
 ACTIVITY_DATE            ||         
 SYS_CREATION_DATE        ||         
 SYS_UPDATE_DATE          ||         
 OPERATOR_ID              ||         
 APPLICATION_ID           ||         
 DL_SERVICE_CODE          ||         
 DL_UPDATE_STAMP          ||         
 APPROVAL_INDICATOR       ||         
 MEMO_ID                  ||         
 REASON_CODE              ||         
 STEP_ID                  ||         
 POLICY_CODE         ||                
 PA_IND   ) in (select 
 ENTITY_KEY              ||            
 ENTITY_ID               ||            
 ENTITY_TYPE             ||            
 ACTIVITY_CODE           ||            
 ACTIVITY_DATE           ||            
 SYS_CREATION_DATE       ||            
 SYS_UPDATE_DATE         ||            
 OPERATOR_ID             ||            
 APPLICATION_ID          ||            
 DL_SERVICE_CODE         ||            
 DL_UPDATE_STAMP         ||            
 APPROVAL_INDICATOR      ||            
 MEMO_ID                 ||            
 REASON_CODE             ||            
 STEP_ID                 ||            
 POLICY_CODE              ||           
 PA_IND   from mig_tmp.TREATMENT_ACTIVITY_ext)
 
9325754 rows deleted.
Elapsed: 00:02:24.24
SQL> commit;
Commit complete.

 SQL> insert into TREATMENT_ACTIVITY select *from mig_tmp.TREATMENT_ACTIVITY_ext;
4662877 rows created.
Elapsed: 00:00:18.44
SQL> commit;
Commit complete.

这样数据就能完全对上了。这个问题根本原因就是null导致的。可以使用如下的例子来简单演示一下。
SQL> create table test(id number,name varchar2(10));
insert into test values(1,null);
insert into test values(2,1);
insert into test values(3,1)


create table test2 (id number,name varchar2(10));
insert into test values(1,null);
insert into test values(2,1);
insert into test values(3,1)

Table created.
SQL> 
1 row created.
SQL> 
1 row created.
SQL>   2  SQL> 
Table created.
SQL> 
1 row created.
SQL> 
1 row created.
SQL> 

现在我们来使用相同的方式来查询。可以看到根本的原因就是null
SQL> select count(*)from test where (id,name) in (select id,name from test2)
  2  /
  COUNT(*)
----------
         0


目录
相关文章
|
2天前
|
云安全 数据采集 人工智能
古茗联名引爆全网,阿里云三层防护助力对抗黑产
阿里云三层校验+风险识别,为古茗每一杯奶茶保驾护航!
古茗联名引爆全网,阿里云三层防护助力对抗黑产
|
6天前
|
人工智能 中间件 API
AutoGen for .NET - 架构学习指南
《AutoGen for .NET 架构学习指南》系统解析微软多智能体框架,涵盖新旧双架构、核心设计、技术栈与实战路径,助你从入门到精通,构建分布式AI协同系统。
302 142
|
6天前
|
Kubernetes 算法 Go
Kubeflow-Katib-架构学习指南
本指南带你深入 Kubeflow 核心组件 Katib,一个 Kubernetes 原生的自动化机器学习系统。从架构解析、代码结构到技能清单与学习路径,助你由浅入深掌握超参数调优与神经架构搜索,实现从使用到贡献的进阶之旅。
281 139
|
2天前
|
存储 机器学习/深度学习 人工智能
大模型微调技术:LoRA原理与实践
本文深入解析大语言模型微调中的关键技术——低秩自适应(LoRA)。通过分析全参数微调的计算瓶颈,详细阐述LoRA的数学原理、实现机制和优势特点。文章包含完整的PyTorch实现代码、性能对比实验以及实际应用场景,为开发者提供高效微调大模型的实践指南。
362 0
|
3天前
|
传感器 人工智能 算法
数字孪生智慧水务系统,三维立体平台,沃思智能
智慧水务系统融合物联网、数字孪生与AI技术,实现供水全流程智能监测、预测性维护与动态优化。通过实时数据采集与三维建模,提升漏损控制、节能降耗与应急响应能力,推动水务管理从经验驱动迈向数据驱动,助力城市水资源精细化、可持续化管理。
264 142
|
1天前
|
存储 人工智能 Java
AI 超级智能体全栈项目阶段四:学术分析 AI 项目 RAG 落地指南:基于 Spring AI 的本地与阿里云知识库实践
本文介绍RAG(检索增强生成)技术,结合Spring AI与本地及云知识库实现学术分析AI应用,利用阿里云Qwen-Plus模型提升回答准确性与可信度。
191 90
AI 超级智能体全栈项目阶段四:学术分析 AI 项目 RAG 落地指南:基于 Spring AI 的本地与阿里云知识库实践
|
17天前
|
存储 关系型数据库 分布式数据库
PostgreSQL 18 发布,快来 PolarDB 尝鲜!
PostgreSQL 18 发布,PolarDB for PostgreSQL 全面兼容。新版本支持异步I/O、UUIDv7、虚拟生成列、逻辑复制增强及OAuth认证,显著提升性能与安全。PolarDB-PG 18 支持存算分离架构,融合海量弹性存储与极致计算性能,搭配丰富插件生态,为企业提供高效、稳定、灵活的云数据库解决方案,助力企业数字化转型如虎添翼!
|
2天前
|
机器学习/深度学习 人工智能 运维
智能照明稳压节能控制器,路灯节能稳压系统,沃思智能
智能照明调控柜集电力分配、远程控制与能耗管理于一体,支持自动调光、场景切换与云平台运维,广泛应用于市政、商业及工业领域,显著节能降耗,助力智慧城市建设。
180 137
kde
|
2天前
|
人工智能 关系型数据库 PostgreSQL
n8n Docker 部署手册
n8n是一款开源工作流自动化平台,支持低代码与可编程模式,集成400+服务节点,原生支持AI与API连接,可自托管部署,助力团队构建安全高效的自动化流程。
kde
242 3