Sql 审计表触发器

Sql 审计表触发器,sql,triggers,oracle12c,Sql,Triggers,Oracle12c,尝试创建触发器,以便在对基表进行更改之前使用旧数据填充审核表 CREATE OR REPLACE TRIGGER populate_audit_table BEFORE INSERT OR UPDATE OF cost, retail OR DELETE ON books REFERENCING NEW as new OLD as old FOR EACH ROW DECLARE dml_operation varchar2(1) := CASE WHEN UPDATING THEN '

尝试创建触发器,以便在对基表进行更改之前使用旧数据填充审核表

CREATE OR REPLACE TRIGGER populate_audit_table
BEFORE INSERT OR UPDATE OF cost, retail OR DELETE
ON books
REFERENCING NEW as new OLD as old
FOR EACH ROW
DECLARE
    dml_operation varchar2(1) :=
CASE WHEN UPDATING THEN 'U'
     WHEN DELETING THEN 'D' 
     ELSE 'I'
END;
BEGIN
      INSERT INTO cost_retail_history
        (isbn
        ,title
        ,pubid
        ,pubdate
        ,cost
        ,retail
        ,discount
        ,category
        ,dml_operation)
        SELECT
            (old.isbn
            ,old.title
            ,old.pubid
            ,old.pubdate
            ,old.cost
            ,old.retail
            ,old.discount
            ,old.category
            ,new.dml_operation)
            FROM BOOKS;
    end;
我得到以下错误:

错误:触发器填充\u审核\u表

行/Col:8/7 PL/SQL:SQL语句被忽略

行/列:20/13 PL/SQL:ORA-00907:缺少右括号

我还尝试在INSERT INTO中使用值,而不是指定源表(“从书本中”)

我得到以下错误:

行/Col:8/7 PL/SQL:SQL语句被忽略

行/列:27/18 PL/SQL:ORA-00984:此处不允许使用列

我读了又读,所以我觉得我错过了一些简单的东西,只是需要一个正确的方向

谢谢

编辑: 我放弃了dml_操作,因为这不是必需的,并遵循了下面的建议,但仍然会出现错误:

当前版本:

CREATE OR REPLACE TRIGGER cost_retail_history 
BEFORE INSERT 
OR UPDATE OF cost, retail 
OR DELETE 
ON books 
REFERENCING NEW as new OLD as old
FOR EACH ROW
BEGIN 
  CASE 
    WHEN INSERTING THEN 
        INSERT INTO cost_retail_history
        (isbn
        ,title
        ,pubid
        ,pubdate
        ,cost
        ,retail
        ,discount
        ,category)
        VALUES
        (:new.isbn
        ,:new.title
        ,:new.pubid
        ,:new.pubdate
        ,:new.cost
        ,:new.retail
        ,:new.discount
        ,:new.category)
    WHEN UPDATING cost, retail OR DELETING THEN 
        INSERT INTO cost_retail_history
        (isbn
        ,title
        ,pubid
        ,pubdate
        ,cost
        ,retail
        ,discount
        ,category)
        VALUES
        (:old.isbn
        ,:old.title
        ,:old.pubid
        ,:old.pubdate
        ,:old.cost
        ,:old.retail
        ,:old.discount
        ,:old.category);
  END CASE;
END;
我得到了错误信息:

错误:触发成本\零售\历史记录

行/Col:4/9 PL/SQL:SQL语句被忽略

行/Col:22/5 PL/SQL:ORA-00933:SQL命令未正确结束

我不能确切地说出错误在哪一行,因为这表明它与:

…或删除

…,:新标题


这对我来说毫无意义。

如果您正在执行
插入。。。选择…
则列列表周围不应有括号;i、 e:

      INSERT INTO cost_retail_history
        (isbn
        ...
        ,dml_operation)
        SELECT
            old.isbn
            ...
            ,new.dml_operation
            FROM BOOKS;
但是您不应该从触发器所针对的表中进行选择,部分原因是您将得到一个变异表错误,并且您正在尝试为基表中的每一行插入一个审计行;但主要是因为你已经掌握了你需要的所有信息

使用
values
类,您需要在旧值/新值前面加一个冒号:

....VALUES
            (:old.isbn
            ,:old.title
            ,:old.pubid
            ,:old.pubdate
            ,:old.cost
            ,:old.retail
            ,:old.discount
            ,:old.category
            ,:new.dml_operation);
    end;

Oracle有内置的审计工具,但这大概是一个练习

我不能确切地说出错误在哪一行,因为这表明

这可能与触发器有点混淆,因为它们是SQL和PL/SQL的混合体。因为您会遇到PL/SQL错误,所以行编号从PL/SQL部分的开头开始,因此这里的
BEGIN
是第1行,
INSERT
是第4行<代码>更新时…是第22行

这些新错误只是因为第一条
INSERT
语句末尾没有分号:

        ,:new.discount
        ,:new.category);
-----------------------^
    WHEN UPDATING cost, retail OR DELETING THEN 
        INSERT INTO cost_retail_history

针对第22行报告错误,因为它希望看到分号的位置是
WHEN
,并且它看到上一个SQL命令的第一个点尚未完成。第4行的错误是指出未结束命令的起始位置;因此,对于一个实际问题,您收到了两条消息。

我听从了亚历克斯·普尔的建议,但我仍然不在那里。谢谢你的回答,它澄清了我的参考哪里出错了。我更新了我的回答,以涵盖新的错误,并解释错误消息中的行号。
        ,:new.discount
        ,:new.category);
-----------------------^
    WHEN UPDATING cost, retail OR DELETING THEN 
        INSERT INTO cost_retail_history