使用 oracle 触发器创建审计跟踪

create audit trail using oracle trigger

我正在尝试创建一个触发器来审核所有新列和旧列或更新、插入的每一行。这是 table

ID  NUMBER(10,0)    No      1   
ENTITY_ID   NUMBER(10,0)    No      2   
LOCATION_ID NUMBER(10,0)    Yes     3   
NAME    VARCHAR2(128 CHAR)  No      4   
CREATED_BY  VARCHAR2(255 CHAR)  No  'unknown'   5   
UPDATED_BY  VARCHAR2(255 CHAR)  No  'unknown'   6   
TS_CREATED  TIMESTAMP(6)    No  "SYSTIMESTAMP
   "    7

我不知道怎么写触发器。

CREATE OR REPLACE TRIGGER audit_security_zones
  BEFORE DELETE OR INSERT OR UPDATE ON security_zones
  FOR EACH ROW
DECLARE

BEGIN

END;

我还想使用来自应用程序的客户端标识符 senbt。这是我的审计线索 table.

ID  NUMBER(10,0)    No      1   
ACTION  VARCHAR2(20 BYTE)   Yes     2   
TABLE_ID    VARCHAR2(100 BYTE)  Yes     3   
OLD_VALUE   VARCHAR2(1000 BYTE) Yes     4   
NEW_VALUE   VARCHAR2(1000 BYTE) Yes     5   
USERNAME    VARCHAR2(100 BYTE)  Yes     6   
TS_UPDATED  TIMESTAMP(6)    No  systimestamp    7

这样做好吗?然后,我将根据每个 table 为用户呈现一个视图,向他们展示发生了什么变化。

更新

我正在尝试实现类似于以下内容的东西

CREATE OR REPLACE TRIGGER audit_security_zones
  BEFORE DELETE OR INSERT OR UPDATE ON security_zones
  FOR EACH ROW
DECLARE
    var_action CHAR(1);
BEGIN
    IF INSERTING   THEN var_action := 'INSERT';
    ELSIF UPDATING THEN var_action := 'UPDATE';
    ELSE                var_action := 'DELETE';
    END IF;

    /* loop eahc column in the update or insert or delete statement executed */
    for each col in stmt/row{
    INSERT INTO audit_table
    (
    ACTION,
    TABLE_ID,
    OLD_VALUE,
    NEW_VALUE,
    USERNAME,
    TS_CREATED
    ) VALUES (
    var_action,
    :OLD.ID,
    :OLD.columnVALUE,
    :new.COLUMNVALUE,
    ociidentifier,
    systimestamp
    )
    }
END;

更新2

CREATE OR REPLACE TRIGGER audit_security_zones
  BEFORE DELETE OR INSERT OR UPDATE ON security_zones
  FOR EACH ROW
DECLARE
    var_action CHAR(6);
BEGIN
    IF INSERTING   THEN var_action := 'INSERT';
    ELSIF UPDATING THEN var_action := 'UPDATE';
    ELSE                var_action := 'DELETE';
    END IF;

    IF var_action = 'DELETE' THEN
        INSERT INTO audit_table
        (
            ACTION,
            USERNAME,
            ID,
            O_ENTITY_ID,
            O_LOCATION_ID,
            O_NAME,
            O_CREATED_BY,
            O_UPDATED_BY,
            O_TS_CREATED            
        ) VALUES (
            var_action,
            USERNAME,
            :OLD.ID,
            :OLD.ENTITY_ID,
            :OLD.LOCATION_ID,
            :OLD.NAME,
            :OLD.CREATED_BY,
            :OLD.UPDATED_BY,
            :OLD.TS_CREATED         
        );
    ELSEIF var_action = 'INSERT' THEN
        INSERT INTO audit_table
        (
            ACTION,
            USERNAME,
            ID,         
            N_ENTITY_ID,
            N_LOCATION_ID,
            N_NAME,
            N_CREATED_BY,
            N_UPDATED_BY
            N_TS_CREATED
        ) VALUES (
            var_action,
            USERNAME,
            :NEW.ID,            
            :NEW.ENTITY_ID,
            :NEW.LOCATION_ID,
            :NEW.NAME,
            :NEW.CREATED_BY,
            :NEW.UPDATED_BY,
            :NEW.TS_CREATED
        );
    ELSEIF var_action = 'UPDATE' THEN
        INSERT INTO audit_table
        (
            ACTION,
            USERNAME,
            ID,
            O_ENTITY_ID,
            O_LOCATION_ID,
            O_NAME,
            O_CREATED_BY,
            O_UPDATED_BY,
            O_TS_CREATED,
            N_ENTITY_ID,
            N_LOCATION_ID,
            N_NAME,
            N_CREATED_BY,
            N_UPDATED_BY
            N_TS_CREATED
        ) VALUES (
            var_action,
            USERNAME,
            :OLD.ID,
            :OLD.ENTITY_ID,
            :OLD.LOCATION_ID,
            :OLD.NAME,
            :OLD.CREATED_BY,
            :OLD.UPDATED_BY,
            :OLD.TS_CREATED,
            :NEW.ENTITY_ID,
            :NEW.LOCATION_ID,
            :NEW.NAME,
            :NEW.CREATED_BY,
            :NEW.UPDATED_BY,
            :NEW.TS_CREATED
        );
    END IF;
END;

我收到以下错误

Error(31,9): PLS-00103: Encountered the symbol "VAR_ACTION" when expecting one of the following:     := . ( @ % ; 
Error(42,4): PLS-00103: Encountered the symbol "N_TS_CREATED" when expecting one of the following:     . ) , @ The symbol "." was substituted for "N_TS_CREATED" to continue. 
Error(54,12): PLS-00103: Encountered the symbol "VAR_ACTION" when expecting one of the following:     := . ( @ % ; 
Error(71,4): PLS-00103: Encountered the symbol "N_TS_CREATED" when expecting one of the following:     . ) , @ The symbol "." was substituted for "N_TS_CREATED" to continue. 
Error(90,4): PLS-00103: Encountered the symbol ";" when expecting one of the following:     if 

更新3

CREATE OR REPLACE TRIGGER audit_security_zones
  BEFORE DELETE OR INSERT OR UPDATE ON security_zones
  FOR EACH ROW
DECLARE
    var_action CHAR(6);
BEGIN
    IF INSERTING   THEN var_action := 'INSERT';
    ELSIF UPDATING THEN var_action := 'UPDATE';
    ELSE                var_action := 'DELETE';
    END IF;

    IF var_action = 'DELETE' THEN
        INSERT INTO audit_table
        (
            ACTION,
            USERNAME,
            ID,
            O_ENTITY_ID,
            O_LOCATION_ID,
            O_NAME,
            O_CREATED_BY,
            O_UPDATED_BY,
            O_TS_CREATED            
        ) VALUES (
            var_action,
            USERNAME,
            :OLD.ID,
            :OLD.ENTITY_ID,
            :OLD.LOCATION_ID,
            :OLD.NAME,
            :OLD.CREATED_BY,
            :OLD.UPDATED_BY,
            :OLD.TS_CREATED         
        );
    ELSE IF var_action = 'INSERT' THEN
        INSERT INTO audit_table
        (
            ACTION,
            USERNAME,
            ID,         
            N_ENTITY_ID,
            N_LOCATION_ID,
            N_NAME,
            N_CREATED_BY,
            N_UPDATED_BY,
            N_TS_CREATED
        ) VALUES (
            var_action,
            USERNAME,
            :NEW.ID,            
            :NEW.ENTITY_ID,
            :NEW.LOCATION_ID,
            :NEW.NAME,
            :NEW.CREATED_BY,
            :NEW.UPDATED_BY,
            :NEW.TS_CREATED
        );
    ELSE IF var_action = 'UPDATE' THEN
        INSERT INTO audit_table
        (
            ACTION,
            USERNAME,
            ID,
            O_ENTITY_ID,
            O_LOCATION_ID,
            O_NAME,
            O_CREATED_BY,
            O_UPDATED_BY,
            O_TS_CREATED,
            N_ENTITY_ID,
            N_LOCATION_ID,
            N_NAME,
            N_CREATED_BY,
            N_UPDATED_BY,
            N_TS_CREATED
        ) VALUES (
            var_action,
            USERNAME,
            :OLD.ID,
            :OLD.ENTITY_ID,
            :OLD.LOCATION_ID,
            :OLD.NAME,
            :OLD.CREATED_BY,
            :OLD.UPDATED_BY,
            :OLD.TS_CREATED,
            :NEW.ENTITY_ID,
            :NEW.LOCATION_ID,
            :NEW.NAME,
            :NEW.CREATED_BY,
            :NEW.UPDATED_BY,
            :NEW.TS_CREATED
        );
    END IF;
END;

我现在得到的错误是

Error(90,4): PLS-00103: Encountered the symbol ";" when expecting one of the following:     if 

更新4

    CREATE OR REPLACE TRIGGER audit_security_zones
  BEFORE DELETE OR INSERT OR UPDATE ON security_zones
  FOR EACH ROW
DECLARE
    var_action CHAR(6);
BEGIN
    IF INSERTING   THEN var_action := 'INSERT';
    ELSIF UPDATING THEN var_action := 'UPDATE';
    ELSE                var_action := 'DELETE';
    END IF;

    IF var_action = 'DELETE' THEN
        INSERT INTO audit_table
        (
            ACTION,
            USERNAME,
            ID,
            O_ENTITY_ID,
            O_LOCATION_ID,
            O_NAME,
            O_CREATED_BY,
            O_UPDATED_BY,
            O_TS_CREATED            
        ) VALUES (
            var_action,
            'test',
            :OLD.ID,
            :OLD.ENTITY_ID,
            :OLD.LOCATION_ID,
            :OLD.NAME,
            :OLD.CREATED_BY,
            :OLD.UPDATED_BY,
            :OLD.TS_CREATED         
        );
    ELSIF var_action = 'INSERT' THEN
        INSERT INTO audit_table
        (
            ACTION,
            USERNAME,
            ID,         
            N_ENTITY_ID,
            N_LOCATION_ID,
            N_NAME,
            N_CREATED_BY,
            N_UPDATED_BY,
            N_TS_CREATED
        ) VALUES (
            var_action,
            'test',
            :NEW.ID,            
            :NEW.ENTITY_ID,
            :NEW.LOCATION_ID,
            :NEW.NAME,
            :NEW.CREATED_BY,
            :NEW.UPDATED_BY,
            :NEW.TS_CREATED
        );
    ELSIF var_action = 'UPDATE' THEN
        INSERT INTO audit_table
        (
            ACTION,
            USERNAME,
            ID,
            O_ENTITY_ID,
            O_LOCATION_ID,
            O_NAME,
            O_CREATED_BY,
            O_UPDATED_BY,
            O_TS_CREATED,
            N_ENTITY_ID,
            N_LOCATION_ID,
            N_NAME,
            N_CREATED_BY,
            N_UPDATED_BY,
            N_TS_CREATED
        ) VALUES (
            var_action,
            'test',
            :OLD.ID,
            :OLD.ENTITY_ID,
            :OLD.LOCATION_ID,
            :OLD.NAME,
            :OLD.CREATED_BY,
            :OLD.UPDATED_BY,
            :OLD.TS_CREATED,
            :NEW.ENTITY_ID,
            :NEW.LOCATION_ID,
            :NEW.NAME,
            :NEW.CREATED_BY,
            :NEW.UPDATED_BY,
            :NEW.TS_CREATED
        );
    END IF;
END;

我收到新错误

    Error(9,3): PL/SQL: SQL Statement ignored
Error(19,4): PL/SQL: ORA-00904: "O_TS_CREATED": invalid identifier
Error(32,3): PL/SQL: SQL Statement ignored
Error(42,4): PL/SQL: ORA-00904: "N_TS_CREATED": invalid identifier
Error(55,9): PL/SQL: SQL Statement ignored
Error(71,4): PL/SQL: ORA-00904: "N_TS_CREATED": invalid identifier

您不能 "loop" 通过旧值和新值,您必须明确引用每个值,即

INSERT INTO audit_table
    (
    ACTION,
    TABLE_ID,
    OLD_VALUE,
    NEW_VALUE,
    USERNAME,
    TS_CREATED
    ) VALUES (
    var_action,
    :OLD.ID,
    :OLD.column1VALUE,
    :new.COLUMN1VALUE,
    ociidentifier,
    systimestamp
    );
INSERT INTO audit_table
    (
    ACTION,
    TABLE_ID,
    OLD_VALUE,
    NEW_VALUE,
    USERNAME,
    TS_CREATED
    ) VALUES (
    var_action,
    :OLD.ID,
    :OLD.column2VALUE,
    :new.COLUMN2VALUE,
    ociidentifier,
    systimestamp
    );
... etc.

您可以通过编写一个过程来包装 INSERT 语句并多次调用它而不是 INSERT 语句本身来稍微简化代码。