Как использовать триггер таким образом, чтобы все обновленные столбцы базовой таблицы в несколько строк таблицы аудита? - PullRequest
0 голосов
/ 21 июня 2019

Я пытаюсь вставить старые и новые значения таблицы «Base» в таблицу аудита «Audit».Проблема в том, как хранить данные в таблице аудита.Если будет обновлено более одного столбца, я смогу сохранить его в этом формате.

Структура таблицы «Аудит»

Id | Column_Name | Old_Value | New_Value
 1 | Strike      | 4         | 5
 2 | Spare       | 3         | 7
 3 | Score       | 10        | 18

Мое решение дает следующую структуру

Id | old_strike | new_strike | old_spare | new_spare | old_score | new_score
1  | 4          | 5          | 3         | 7         | 10        | 18

Я пробовал это использовать триггер, чтобы сохранить старое и новое значение в строках, но мне было нелегко выяснить, как пройти для одного оператора вставки для каждого столбца.

AFTER INSERT OR UPDATE OR DELETE ON frame  -- after event
FOR EACH ROW    // fires for each record
BEGIN

INSERT INTO frame_audit(bowler_id,game_id,frame_number,
old_strike,new_strike,
old_spare,new_spare,
old_score,new_score,
change_date,operation)

VALUES(:NEW.bowler_id,:NEW.game_id,:NEW.frame_number,
:OLD.strike,:NEW.strike,
:OLD.spare,:NEW.spare,
:OLD.score,:NEW.score,
SYSDATE,'UPDATE');
END audit_frames```

// Structure of 'Audit' table
Id | Column_Name | Old_Value | New_Value
 1 | Strike      | 4         | 5
 2 | Spare       | 3         | 7
 3 | Score       | 10        | 18

1 Ответ

0 голосов
/ 21 июня 2019

Как уже упоминалось в комментариях, нет возможности извлекать значения OLD и NEW, специфичные для каждого имени столбца, динамически. Все, что вы можете сделать, это написать явные вставки для всех столбцов с жестко закодированными именами столбцов.

 ...
 ...

BEGIN


INSERT INTO frame_audit (Id ,Column_Name , Old_Value , New_Value)
SELECT  audit_seq.nextval,'bowler_id',old.bowler_id,new.bowler_id 
FROM DUAL WHERE 
 (    old.bowler_id <> new.bowler_id OR
      (old.bowler_id is NULL     and new.bowler_id is NOT NULL) OR
      (old.bowler_id is NOT NULL and new.bowler_id is NULL   ) 
 );

INSERT INTO frame_audit (Id ,Column_Name , Old_Value , New_Value)
SELECT  audit_seq.nextval,'game_id',old.game_id,new.game_id 
FROM DUAL WHERE 
 (    old.game_id <> new.game_id OR
      (old.game_id is NULL     and new.game_id is NOT NULL) OR
      (old.game_id is NOT NULL and new.game_id is NULL   ) 
 );

--similar inserts for all other columns


 ...

END;

Здесь я предполагаю, что у вас есть последовательность, созданная для генерации идентификаторов для таблицы аудита.

Вы можете упростить длинное NULL проверочное выражение, используя NVL или COALESCE, но вы должны использовать его в соответствии с типом данных каждого столбца. Если столбец определен как not null, простой проверки <> будет достаточно. Для столбцов, связанных с DATE/TIMESTAMP, вам нужно будет использовать TO_CHAR, если вы хотите сохранить его в нужном формате.

...