简体   繁体   English

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

[英]Oracle 12c - complicated update and delete

I have the following scenario in a auditing table (AUDIT_TABLE). 我在审核表(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

There's a bug in the batch processes that trigger inserts into this audit table and creates these records " Dept_ID: from .. to " when there is no change in the " Dept_ID " value (in another table). 批处理过程中有一个错误,当“ Dept_ID ”值(在另一个表中)没有变化时,它会触发插入此审计表并创建这些记录“ Dept_ID: from .. to ”。 There are millions of these records that need to be cleaned up. 这些记录中有数百万需要清除。 The records that have multiple field changes captured ie item_id 01 needs to be updated to clear the Dept_ID : audit message and the records that have only the Dept_ID audit record needs to be deleted ( item_id 02 ). 需要更新具有多个字段更改的记录,即item_id 01 ,以清除Dept_ID :审核消息,而只有Dept_ID审核记录的记录需要删除( item_id 02 )。 There may be other pairs that have only the Dept ID audit message in both the records, in which case both need to be deleted. 在其他两个记录中,可能还有其他对仅具有Dept ID审核消息的对,在这种情况下,都需要删除两者。 The trigger logic has been fix so no more false records are being created when there is no actual change in the Dept ID , however the records already created during the bug need to be cleaned up. 触发器逻辑已得到修复,因此在Dept ID没有实际更改时不会创建更多错误记录,但是需要清除在Bug期间已经创建的记录。 There may be rows where there is only one record of the pair in which case these do not need to be updated/deleted because the Dept_ID was actually changed to a null or changed from a null to a value. 可能有几行中只有一对记录,在这种情况下,由于Dept_ID实际上已更改为null或从null更改为值,因此不需要更新/删除这些行。

So the following should exist after fixing the above data-set: 因此,修复以上数据集后,应存在以下内容:

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

I have delete and update statements ready to do this but if I delete one record of the pair, then the update won't find the other record since it depends on the deleted record to find it and vice versa for the update statement. 我已经准备好执行删除和更新语句的操作,但是如果删除一对记录中的一条记录,则更新将找不到另一条记录,因为它依赖于已删除的记录来查找更新,反之亦然。 I thought to use the merge statement but not sure how to. 我曾想使用merge语句,但不确定如何使用。 Any ideas? 有任何想法吗?

So assuming such test data 所以假设这样的测试数据

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 ''; 

if I get you right, you want to remove the Dept_ID entry from the first and second row because one of the values is NULL. 如果我Dept_ID正确,您想从第一行和第二行中删除Dept_ID条目,因为其中一个值为NULL。 I added forth row with both NULL value which should be removed as well. 我添加了两个空值都应该删除的行。

The third row remain unchanged, because both value are filled. 第三行保持不变,因为两个值均已填充。

You need this regexp to replace the data 您需要此正则表达式来替换数据

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

Note that the bar in the middle represents OR. 请注意,中间的条表示OR。 The left part matches the departments with to value NULL, the rigth part the department with from value NULL. 左侧部分部门与匹配to NULL值,则分辩部分与该部门from NULL值。

The matched string is replaced with a NULL string. 匹配的字符串将替换为NULL字符串。

To limit the scope of updated records the exact logik of the buggy records must be defined. 为了限制更新记录的范围,必须定义越野车记录的确切逻辑。 Here an example where I expect that both records must have the same e_id and are ordered on t_id 在此示例中,我希望两个记录必须具有相同的e_id并按t_id

Using LEAD and LAG you examines the following and preceeding recods to check if the condition of the change to emtpy and change from empty is fullfilled. 通过使用LEADLAG您可以检查以下和前面的步骤,以检查是否已将 空更改为空从空更改为空

Note that I'm using LIKE to filter the rows to get better performance. 请注意,我使用LIKE来过滤行以获得更好的性能。

Query to final check before the update:) 查询更新前的最终检查:)

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 '';%]') 
;

returns 回报

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

Update 更新

The UPDATE statement is a simple reformulation of the query above using IN (subquery) to limit the scope. 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

To delete the empty audit records after this cleanup is a trivial step. 在此清理之后删除审计记录是一个简单的步骤。

If all of the rows those should remain have a data of Salary: with adjacent colon at the end like in your case, then consider deleting the rows without Salary: ; 如果应该保留所有这些行的数据,如您的情况,最后有相邻冒号的Salary:数据,则可以考虑删除没有Salary:的行Salary:

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

and then updating the detail_log column's data by trimming the rest after Dept_ID: string 然后通过修剪Dept_ID:字符串后的其余部分来更新detail_log列的数据

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

Rextester Demo Rextester演示

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

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