使用触发器审计操作

Posted

技术标签:

【中文标题】使用触发器审计操作【英文标题】:Audit operations with a trigger 【发布时间】:2014-11-15 20:32:18 【问题描述】:

我有一个在特定条件下触发的触发器,当我更新 EMPLOYEES table 中的一些数据时(特别是当 insertingdeletingupdating comm_pctsalary 时)所做的更改注册到下表中:

CREATE TABLE "HR"."AUDIT_E" ("USR" VARCHAR2(30 BYTE) DEFAULT USER,
    "DATE" DATE DEFAULT SYSDATE,
    "DML_TYPE"  VARCHAR2), -- UPDATE, INSERT, DELETE
    "OLD_EMPLOYEE_ID" NUMBER, 
"OLD_FIRST_NAME" VARCHAR2,  
...,--more fields
"OLD_JOB_ID" VARCHAR2, 
"OLD_SALARY" NUMBER, 
"OLD_COMMISSION_PCT" NUMBER,  
"NEW_FIRST_NAME" VARCHAR2, 
..., -- more fields!
"NEW_JOB_ID" VARCHAR2, 
"NEW_SALARY" NUMBER, 
"NEW_COMMISSION_PCT" NUMBER)

我的问题是:当updating rows 带有其他值(如email 带有comm_pct 和其他字段)时,我如何在AUDIT_E 中执行INSERT(因为我必须将旧值和新值注册到其中) ,除了只更新comm_pctsalary)?因为我的触发器有以下结构:

IF DELETING THEN
--some actions
-- Insert into AUDIT_E(...) values...
ELSIF INSERTING THEN
    --some actions
-- Insert into AUDIT_E(...) values...
ELSIF UPDATING ('a field') THEN --I have two of these
    --some actions
-- Insert into AUDIT_E(...) values...comm_pct/salary

非常感谢你能帮助我,对不起我的英语。

编辑:当我在 insertingdeleting 行和 updatingcomm_pctsalary 时,我的触发器运行良好,将更改注册到 audit_e

AUDIT_E:
ID |Oper|Old_Name|Old_job_id|Old_comm_pct|Old_Salary|New_name|New_job_id|New_comm_pct|New_salary
------------------------------------------------------------------------------------------------
1  |Ins |  NULL  | NULL     |  NULL      |   NULL   |Kappa   | SA_REP   | 0.2        | 4980 
2  |Upd | Kappa  | SA_REP   | 0.2        | 4980     | NULL   | NULL     | 0.3        | NULL
3  |Upd | Kappa  | SA_REP   | 0.3        | 4980     | NULL   | NULL     | NULL       | 5000
4  |Del | Kappa  | SA_REP   | 0.3        | 4980     | NULL   | NULL     | NULL       | NULL

但是,例如,当我更改 job_id(添加额外的 elsif 更新)时,更改会错误地保存到 audit_e 中:

AUDIT_E:
ID |Oper|Old_Name|Old_job_id|Old_comm_pct|Old_Salary|New_name|New_job_id|New_comm_pct|New_salary
------------------------------------------------------------------------------------------------
1  |Upd |Kappa   | SA_REP   | 0.2        | 4980     | NULL   | NULL     | NULL        | NULL 

我希望将这些更改保存到 audit_e 表中,如下所示:

 AUDIT_E:
ID |Oper|Old_Name|Old_job_id|Old_comm_pct|Old_Salary|New_name|New_job_id|New_comm_pct|New_salary
------------------------------------------------------------------------------------------------
1  |Upd |Kappa   | SA_REP   | 0.2        | 4980     | NULL   | IT_PROG  | NULL       | NULL 

【问题讨论】:

恐怕我不明白你问的问题。您发布的触发器大纲似乎无效——如果您真的有ELSIF 子句,那么您不会想要所有END IF 的。如果您想拥有多个IF 语句,您将保留END IF 并将ELSIF 替换为IF。但我不相信这是你要问的问题。 我更正了我发布的代码。我的想法是有一个历史表(在本例中为 AUDIT_E),它在员工表中注册所有使用 INSERT、UPDATE 和 DELETE 更改的值。但我的问题是我想注册我的更改,这些更改不仅会更改薪水或 comm_pct 的值,也不会在员工中添加或删除行 触发器在 EMPLOYEES 表上,不是吗?如果是,您拥有所有想要存储在 AUDIT_E 中的数据,不是吗? 触发器正在对员工执行。但我想将数据存储到 audit_e。当我插入一行、删除一行以及更新 comm_pct 和/或薪水时,我可以存储数据。但我希望我的触发器(在 audit_e 中)注册员工所做的其他更改(如更改 job_id、first_name 等) 【参考方案1】:

我仍然不确定我是否理解了这个问题。我的猜测是你只想要类似的东西

CREATE OR REPLACE TRIGGER trigger_name
  AFTER INSERT OR UPDATE OR DELETE
  ON employees
  FOR EACH ROW
BEGIN
  INSERT INTO audit_e( dml_type, 
                       old_employee_id, new_employee_id,
                       old_first_name, new_first_name,
                       ...
                     )
    VALUES( CASE WHEN deleting 
                 THEN 'D'
                 WHEN inserting 
                 THEN 'I'
                 WHEN updating
                 THEN 'U'
                 ELSE 'X'
             END,
            :old.employee_id, :new.employee_id,
            :old.first_name, :new.first_name,
            ...
           );
END;

也就是说,我不清楚您为什么每次都将新旧数据都存储在审计表中。 old_* 值始终与前一行中的 new_ 值相同。将new_ 值存储在审计表中通常是有意义的。

【讨论】:

是的,我需要类似的东西,但仅限于更新情况。我认为添加另一个 ELSIF 子句和一个 INSERT 值可以注册我想要的更改。但是当我更改一些不是 comm_pct 和薪水的值(例如 job_id)时,我的审计表没有正确记录这些更改(:old 值是正确的,但 :new 值在表中保持为空)如果我将该块放入我的代码中。 @RyuukoMatoi - 那我还是不明白你想问的问题。在我的回答中,触发器中没有 IF 语句,每次修改都会记录所有旧值和新值。如果这不是您的目标,那么我不明白这个问题 - 您可以编辑您的问题以包含一个可重现的测试用例,以准确显示您想要发生的事情吗? 现在我编辑了我的问题,更详细地解释了我想要的结果。我很抱歉英语不好。我希望你能明白我想做什么。 @RyuukoMatoi - 我发布的触发器结果与您想要的结果有何不同?我的触发器有 0 个“IF”语句。如果你想让你的生活复杂化,你可以为每一个可以更新的列添加一个“Elsif”。但是,我认为没有任何理由这样做。 我忘了提及,但我的触发器是 BEFORE INSERT UPDATE DELETE。好吧,当我更新 comm_pct 和薪水时,这些值必须保留触发器的某些条件。我会尝试做类似的事情并查看它是如何工作的。感谢您的帮助

以上是关于使用触发器审计操作的主要内容,如果未能解决你的问题,请参考以下文章

AFTER DELETE 触发器触发但不将记录插入审计表

oracle控制何时触发审计动作

使用Trigger审计一张表的DML操作

对审计列使用触发器

使用 oracle 触发器审计 50 列

使用 oracle 触发器审计 50 列