繁体   English   中英

Oracle 12c-复杂的更新和删除

[英]Oracle 12c - complicated update and delete

我在审核表(AUDIT_TABLE)中具有以下情形。

t_id  e_id     detail_log                                                    date_created
01    111      USER_1; Salary: from '25' to '30'; Dept_ID: from '001' to ''; 01/01/2019 
02    111      USER_1; Dept_ID: from '' to '001';                            01/01/2019
03    001      USER_1; Dept_ID: from '012' to '';                            01/01/2019
04    002      USER_1; Dept_ID: from '555' to '666';                         01/01/2019
05    222      USER_1; Dept_ID: from '' to '123';                            01/02/2019
06    333      USER_1; Salary: from '10' to '20'; Dept_ID: from '200' to ''; 01/03/2019
07    444      USER_1; Salary: from '50' to '100'; Dept_ID: from '' to '10'; 01/04/2019

批处理过程中有一个错误,当“ Dept_ID ”值(在另一个表中)没有变化时,它会触发插入此审计表并创建这些记录“ Dept_ID: from .. to ”。 这些记录中有数百万需要清除。 需要更新具有多个字段更改的记录,即item_id 01 ,以清除Dept_ID :审核消息,而只有Dept_ID审核记录的记录需要删除( item_id 02 )。 在其他两个记录中,可能还有其他对仅具有Dept ID审核消息的对,在这种情况下,都需要删除两者。 触发器逻辑已得到修复,因此在Dept ID没有实际更改时不会创建更多错误记录,但是需要清除在Bug期间已经创建的记录。 可能有几行中只有一对记录,在这种情况下,由于Dept_ID实际上已更改为null或从null更改为值,因此不需要更新/删除这些行。

因此,修复以上数据集后,应存在以下内容:

t_id  e_id     detail_log                                                    date_created
01    111      USER_1; Salary: from '25' to '30';                            01/01/2019 
03    001      USER_1; Dept_ID: from '012' to '';                            01/01/2019
04    002      USER_1; Dept_ID: from '555' to '666';                         01/01/2019
05    222      USER_1; Dept_ID: from '' to '123';                            01/02/2019
06    333      USER_1; Salary: from '10' to '20'; Dept_ID: from '200' to ''; 01/03/2019
07    444      USER_1; Salary: from '50' to '100'; Dept_ID: from '' to '10'; 01/04/2019

我已经准备好执行删除和更新语句的操作,但是如果删除一对记录中的一条记录,则更新将找不到另一条记录,因为它依赖于已删除的记录来查找更新,反之亦然。 我曾想使用merge语句,但不确定如何使用。 有任何想法吗?

所以假设这样的测试数据

DETAIL_LOG                                                                              
-----------------------------------------------------------------------------------------
USER_1; Salary: from '25' to '30'; Dept_ID: from '001' to '';                             
USER_1; Dept_ID: from '' to '001';                                                        
USER_1; Salary: from '25' to '30'; Dept_ID: from '001' to '002'; Prdeel: from '0' to '1': 
USER_1; Dept_ID: from '' to ''; 

如果我Dept_ID正确,您想从第一行和第二行中删除Dept_ID条目,因为其中一个值为NULL。 我添加了两个空值都应该删除的行。

第三行保持不变,因为两个值均已填充。

您需要此正则表达式来替换数据

 q'[(Dept_ID: from '.*' to '';|Dept_ID: from '' to '.*';)]'

请注意,中间的条表示OR。 左侧部分部门与匹配to NULL值,则分辩部分与该部门from NULL值。

匹配的字符串将替换为NULL字符串。

为了限制更新记录的范围,必须定义越野车记录的确切逻辑。 在此示例中,我希望两个记录必须具有相同的e_id并按t_id

通过使用LEADLAG您可以检查以下和前面的步骤,以检查是否已将 空更改为空从空更改为空

请注意,我使用LIKE来过滤行以获得更好的性能。

查询更新前的最终检查:)

with al as (
select T_ID, E_ID, DETAIL_LOG, 
lead(DETAIL_LOG) over (partition by e_id  order by t_id) DETAIL_LOG_LEAD,
lag(DETAIL_LOG) over (partition by e_id  order by t_id) DETAIL_LOG_LAG
from AUDIT_TABLE)
select T_ID, E_ID,
/* updated entry */
regexp_replace(detail_log, q'[(Dept_ID: from '.*' to '';|Dept_ID: from '' to '.*';)]', '') DETAIL_LOG
from al
where (DETAIL_LOG      like q'[%Dept_ID: from '_%' to '';%]' and /* first wrong record */
       DETAIL_LOG_LEAD like q'[%Dept_ID: from '' to '_%';%]') OR
      (DETAIL_LOG      like q'[%Dept_ID: from '' to '_%';%]' and /* second wrong record */
       DETAIL_LOG_LAG  like q'[%Dept_ID: from '_%' to '';%]') 
;

回报

      T_ID       E_ID DETAIL_LOG                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
---------- ---------- ------------
         1        111 USER_1; Salary: from '25' to '30';                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
         2        111 USER_1;

更新

UPDATE语句是使用IN (子查询)来限制范围的上述查询的简单重构。

update AUDIT_TABLE
set DETAIL_LOG = regexp_replace(detail_log, q'[(Dept_ID: from '.*' to '';|Dept_ID: from '' to '.*';)]', '')
where (T_ID, E_ID) in 
-- query from above that limits the updated rows

在此清理之后删除审计记录是一个简单的步骤。

如果应该保留所有这些行的数据,如您的情况,最后有相邻冒号的Salary:数据,则可以考虑删除没有Salary:的行Salary:

delete audit_table where instr(detail_log,'Salary:') = 0;

然后通过修剪Dept_ID:字符串后的其余部分来更新detail_log列的数据

update audit_table 
   set detail_log = regexp_replace(detail_log, '(.*)Dept_ID:.*', '\1');

Rextester演示

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM