[英]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. 通过使用
LEAD
和LAG
您可以检查以下和前面的步骤,以检查是否已将 空更改为空或从空更改为空 。
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');
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.