Oracle 12c - сложное обновление и удаление - PullRequest
0 голосов
/ 13 января 2019

У меня есть следующий сценарий в таблице аудита (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: from .. to", когда значение "Dept_ID" не изменяется (в другой таблице). Есть миллионы этих записей, которые необходимо очистить. Записи, в которых зафиксировано несколько изменений полей, т. Е. item_id 01 необходимо обновить, чтобы очистить сообщение аудита Dept_ID:: и записи, содержащие только запись аудита Dept_ID, должны быть удалены (item_id 02). Могут быть другие пары, которые имеют только контрольное сообщение Dept ID в обеих записях, и в этом случае обе должны быть удалены. Логика триггера была исправлена, поэтому больше нет ложных записей, когда нет фактических изменений в Dept ID, однако записи, уже созданные во время ошибки, необходимо очистить. Могут быть строки, в которых есть только одна запись пары, в этом случае их не нужно обновлять / удалять, потому что Dept_ID был фактически изменен на ноль или изменен с нуля на значение.

Таким образом, после исправления вышеуказанного набора данных должно существовать следующее:

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

У меня есть операторы удаления и обновления, готовые сделать это, но если я удаляю одну запись из пары, то обновление не найдет другую запись, так как ее поиск зависит от удаленной записи, и наоборот, для оператора обновления , Я думал использовать оператор слияния, но не уверен, как это сделать. Есть идеи?

Ответы [ 2 ]

0 голосов
/ 13 января 2019

Итак, при условии, что такие тестовые данные

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 из первой и второй строки, потому что одно из значений - NULL. Я добавил четвертую строку со значением NULL, которое также должно быть удалено.

Третья строка остается неизменной, поскольку оба значения заполнены.

Вам нужно это регулярное выражение для замены данных

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

Обратите внимание, что столбец в середине представляет ИЛИ. Левая часть соответствует отделам со значением to NULL, а правая часть - отделу со значением from NULL.

Соответствующая строка заменяется пустой строкой.

Чтобы ограничить область действия обновляемых записей, необходимо определить точный логик ошибочных записей. Вот пример, где я ожидаю, что обе записи должны иметь одинаковые e_id и упорядочены по t_id

Используя LEAD и LAG, вы проверяете следующие и предыдущие повторы, чтобы убедиться, что условие изменяется на emtpy и меняется с пустого заполнено.

Обратите внимание, что я использую 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

Удаление пустых записей аудита после этой очистки является тривиальным шагом.

0 голосов
/ 13 января 2019

Если все эти строки должны иметь данные Salary: со смежным двоеточием в конце, как в вашем случае, рассмотрите возможность удаления строк без Salary:;

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

, а затем обновить данные столбца detail_log, обрезав остаток после Dept_ID: string

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

Rextester Demo

...