pl sql触发器。插入和删除表

时间:2013-03-26 10:58:06

标签: oracle plsql triggers

在sql server中触发触发器时,会创建2个临时表。一个是inserted表,其中包含触发器所属的原始表的行,其中发生了插入或更新(它包含:NEW值);另一个是已删除的表,它同样包含OLD值。

在sql Server中,可以在触发器中使用这些表,以便获得有关OLD和NEW值的信息。 (为了做一个简单的例子:可以在触发器内部进行“SELECT * FROM INSERTED”,以便选择已进行更新的所有行或插入时所有插入的行)。

关于这一点很酷的是,它可以动态调用:NEW.value和:OLD.value,如果像我的情况一样,我想在更多的表上使用相同的触发器(也是不同的一个另一个)。

Oracle pl sql有类似内容吗?

2 个答案:

答案 0 :(得分:1)

我认为您正在审核该表,请查找有关插入,更新和删除审核的触发器

编辑:由于phantom建议您在插入审计表之前需要检查每个列的新值和旧值。这样您就可以实现列值的更改。但是,您需要在审计中插入多行table,如果已经更新了同一条记录的多列。

我的想法是在更新/删除/插入审计表之前创建相同记录的副本。当您需要更改时,根据source_action / source_rowid与审计表中的上一条记录进行比较

    CREATE TABLE table_for_audit
    (
       col1       NUMBER,
       col2       NUMBER,
       col3       NUMBER,
       cre_date   DATE,
       cre_user   VARCHAR2 (200)
    );

    CREATE TABLE audit_table
    (
       col1            NUMBER,
       col2            NUMBER,
       col3            NUMBER,
       cre_date        DATE,
       cre_user        VARCHAR2 (200),
       source_action   VARCHAR2 (1),
       source_rowid
    );

    CREATE OR REPLACE TRIGGER trg_table_audit
       BEFORE INSERT OR UPDATE OR DELETE
       ON table_for_audit
       REFERENCING NEW AS NEW OLD AS OLD
       FOR EACH ROW
    DECLARE
       v_source_action   VARCHAR2 (1);
    BEGIN
       IF INSERTING
       THEN
          v_source_action := 'I';
          v_source_rowid := :NEW.ROWID;
       ELSIF UPDATING
       THEN
          v_source_action := 'U';
          v_source_rowid := :OLD.ROWID;
       ELSIF DELETING
       THEN
          v_source_action := 'D';
          v_source_rowid := :OLD.ROWID;
       END IF;


       IF INSERTING OR UPDATING
       THEN
          INSERT INTO audit_table (col1,
                                   col2,
                                   col3,
                                   cre_date,
                                   cre_user,
                                   source_action,
                                   source_rowid)
               VALUES (:NEW.col1,
                       :NEW.col2,
                       :NEW.col3,
                       SYSDATE,
                       SYS_CONTEXT ('USERENV', 'CURRENT_USER'),
                       v_source_action,
                       v_source_rowid);
       ELSIF DELETING
       THEN
          INSERT INTO audit_table (col1,
                                   col2,
                                   col3,
                                   cre_date,
                                   cre_user,
                                   source_action,
                                   source_rowid)
               VALUES (:OLD.col1,
                       :OLD.col2,
                       :OLD.col3,
                       SYSDATE,
                       SYS_CONTEXT ('USERENV', 'CURRENT_USER'),
                       v_source_action,
                       v_source_rowid);
       END IF;
    END;
    /

如果我的理解错误,请纠正。谢谢

答案 1 :(得分:0)

您希望在触发器中使用referencing子句。官方图表为here,但我发现this page更好地解释了它。

基本上,您可以创建触发器:

CREATE OR REPlACE TRIGGER trigger_name
AFTER DELETE OR INSERT OR UPDATE
ON table_name
REFERENCING OLD AS oldAlias AND NEW AS newAlias
...

现在,您可以将预触发和后触发值引用为:oldAlias.column_name:newAlias.column_name

例如,这将检查personnel_type值是否从1更新为2:

IF :oldAlias.personnel_type = 1 AND :newAlias.personnel_type = 2 THEN 
  -- do something
END IF ;

从我可以收集的内容来看,听起来你想要创建一个单独的触发器来监控多个表。 Oracle触发器不能像那样工作。您希望监控的每个表都必须有自己独立的触发器。但是,您可以:

  • 从触发器调用一个过程/函数,向它传递有问题的值(只是确保不会卡在递归/变异触发器中这样做
  • 使用自己的触发器创建单独的审计表。更新源表时,将更改/数据(例如表名或列)推送到审计表。然后审计表的触发器可以处理你想要的那个。