如何在表上创建触发器以识别特定记录是否已被删除/更新并存储更新实体的信息?

时间:2016-05-17 04:14:07

标签: database plsql triggers

我需要在另一个临时表中保存信息,例如,TableTemp正在修改记录,还有一个列定义哪个实体更新了它。

1 个答案:

答案 0 :(得分:1)

你看起来像是在发现,并且提出了非常广泛的问题。但是,这是一个可能的解决方案,假设如下:

  • a_sqnc是您将在TableTemp中使用的序列,用于跟踪列NO_ORD中的操作顺序(即使还有一个D_UPD列,修改时间)。
create sequence a_sqnc
minvalue 1
maxvalue 99999999
start with 1
increment by 1
nocache;
  • TableTemp会有TABLE_NAME列,以便跟踪来自不同表格的更改。它还有PK_VALUEROW_VALUE,我们存储更改的数据。以下是使用有用索引创建的表:
create table TableTemp (
  table_name VARCHAR2(50) not null,
  action     VARCHAR2(240) not null,
  no_ord     NUMBER(12) not null,
  nature     VARCHAR2(3) not null,
  pk_value   VARCHAR2(4000),
  row_value  VARCHAR2(4000),
  ori        VARCHAR2(250),
  c_user     VARCHAR2(20),
  d_upd      DATE
);

create index AP_D_UPD on TableTemp (D_UPD);
create index AP_NO_ORD on TableTemp (NO_ORD);
create index AP_TABLE_NAME on TableTemp (TABLE_NAME);
  • 假设您有一个简单的表BANK,其中包含两列PK_val(主键)和val
create table BANK (
  pk_val VARCHAR2(50) not null,
  val    VARCHAR2(240) not null
);

alter table BANK
  add constraint BK_PK primary key (pk_val)
  using index ;
  • 使用DBMS_APPLICATION_INFO.READ_MODULE(w_sess_mod, w_sess_act)了解哪个模块以及操作的操作:我在ORI中的TableTemp列中连接;

  • user Oracle会话变量可让您跟踪在c_user列中进行更改的人员;

  • 以下是如何创建触发器AUD_BNK来跟踪表BANK中的更改;它将分为3个操作:DELETEUPDATEINSERT(如果需要,您可以删除INSERT个案例。)

CREATE OR REPLACE TRIGGER "AUD_BNK" 
AFTER DELETE OR INSERT OR UPDATE
   ON BANQUE
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW

DECLARE
    w_a        VARCHAR2(10);
    W_ERRM     VARCHAR2(1000);
    W_CODE     VARCHAR2(1000);
    w_n        VARCHAR2(200) := 'BANK';
    w_id       NUMBER :=  a_sqnc.nextval;
    w_act      v$session.action%type;
    w_mod      v$session.module%type;
    w_ori      TableTemp.ORI%TYPE;

  BEGIN
  DBMS_APPLICATION_INFO.READ_MODULE(w_mod, w_act);
  w_ori := 'Module : '||w_mod ||' ; Action : '||w_act;
  ----------------------------------
  -- test which action is for change
  ----------------------------------
  IF UPDATING
  THEN
    w_a := 'UPDATE';
  ELSIF DELETING
  THEN
    w_a := 'DELETE';
  ELSIF INSERTING
  THEN
    w_a := 'INSERT';
  END IF;
  ----------------------------------
  -- Insert into TableTemp 
  ----------------------------------
If w_a in ('UPDATE', 'DELETE') then
  Insert into TableTemp 
       Select w_n, w_a, w_id, 'OLD', :OLD.pk_val, :OLD.val
            , w_ori, user, sysdate
         From Dual;
End if;

-- if you update, there is a new value and an old value
If w_a in ('UPDATE', 'INSERT') then
  Insert into TableTemp 
       Select w_n, w_a, w_id, 'NEW', :NEW.pk_val, :NEW.val
            , w_ori, user, sysdate
         From Dual;
End if;

Exception
When others then
  Begin
    W_ERRM := SQLERRM;
    W_CODE := SQLCODE;
    -- try inserting in case of error anyway
    Insert into TableTemp 
         Select w_n, w_a, -1, 'ERR', 'Grrr: '||W_CODE, W_ERRM
              , w_ori, user, sysdate
     From Dual;
  End;
End;
/

小心!

如果表格发生变化,这种跟踪表格上每个变化的方式将严重影响性能。但对于几乎没有变化的参数表来说非常棒。