【问题标题】:Creating a audit trigger which update a audit table automatically创建一个自动更新审计表的审计触发器
【发布时间】:2021-05-20 00:01:20
【问题描述】:

我的桌子是

Book

CREATE TABLE Book 
(
    Bk_id CHAR(06)NOT NULL,
    BK_Name VARCHAR(60)NOT NULL,
    Author VARCHAR(30)NOT NULL,
    Price NUMERIC(03)NOT NULL,
    No_of_copies NUMERIC(02)NOT NULL,
    CONSTRAINT Book_PK PRIMARY KEY (Bk_id) 
);

Location

CREATE TABLE Location 
(
    Loc_id CHAR(06)NOT NULL,
    Loc_Name VARCHAR(15)NOT NULL,
    Stock NUMERIC(02)NOT NULL,
    CONSTRAINT Location_PK PRIMARY KEY (Loc_id)
);

Customer

CREATE TABLE Customer 
(
    Cus_id CHAR(06)NOT NULL, 
    Cus_Name VARCHAR(25)NOT NULL,  
    Gender VARCHAR(06)NOT NULL, 
    TP CHAR(12)NOT NULL,
    Address VARCHAR(40)NOT NULL, 
    CONSTRAINT Customer_PK PRIMARY KEY (Cus_id)
);

Copy

CREATE TABLE Copy 
(
Copy_id CHAR(06)NOT NULL,
Bk_id CHAR(06)NOT NULL,
Loc_id CHAR(06)NOT NULL,
Opinion CHAR(02)NOT NULL,
CONSTRAINT pk_Copy PRIMARY KEY (Copy_id),
CONSTRAINT fk_Copy_Bk_id_FK FOREIGN KEY (Bk_id) REFERENCES Book(Bk_id),
CONSTRAINT fk_Copy_Loc_id_FK FOREIGN KEY (Loc_id) REFERENCES Location(Loc_id)
);

Borrow

CREATE TABLE Borrow 
(
    Cus_evo NUMERIC(02)NOT NULL,
    B_Date DATE NOT NULL,
    R_Date DATE NOT NULL,
    Fee NUMERIC(03)NOT NULL,
    Copy_id CHAR(06)NOT NULL,
    Cus_id CHAR(06)NOT NULL,
    CONSTRAINT pk_Borrow PRIMARY KEY (Cus_id,Copy_id),
    CONSTRAINT fk_Borrow_Copy_id_FK FOREIGN KEY (Copy_id) REFERENCES Copy(Copy_id),
    CONSTRAINT fk_Borrow_Cus_id_FK FOREIGN KEY (Cus_id) REFERENCES Customer(Cus_id)
);

Audit_Table

Create table Audit_Table
(
Cus_Name VARCHAR(25)NOT NULL,
BK_Name VARCHAR(60)NOT NULL,
B_Date DATE NOT NULL,
Loc_Name VARCHAR(15)NOT NULL,
Cus_evo NUMERIC(02)NOT NULL
);

如果客户给出零评价Cus_evo=0,他们的借款详情(Cus_Name from CUSTOMERBK_Name from BookB_Date from BorrowLoc_Name来自LocationCus_evo 来自Borrow 的副本)必须放在审计表中。

我创建的触发器:

CREATE OR REPLACE TRIGGER "AUDIT_TRIGGER"
BEFORE
INSERT OR UPDATE ON Borrow
FOR EACH ROW
WHEN (new.Cus_evo=0)
BEGIN
INSERT INTO Audit_Table
VALUES (:OLD.Cus_Name, :OLD.BK_Name, :OLD.B_Date, :OLD.Loc_Name, :OLD.Cus_evo);
END;
/

我收到此错误:

错误:TRIGGER AUDIT_TRIGGER 行/列:3/9 PLS-00049:绑定变量“OLD.CUS_NAME”错误 行/列:3/24 PLS-00049:绑定变量“OLD.BK_NAME”错误 行/列:3/51 PLS-00049:错误绑定变量“OLD.LOC_NAME”

【问题讨论】:

  • 在创建表借用时,我们需要表复制。没有表复制你会得到一个错误。
  • 您的触发器和@VBoka 修改的触发器在插入时失败。当触发器在插入时触发时,OLD Pseudo 记录中没有值 - 所有列都是 NULL。请参阅2 Day Developers Guide中的“关于旧和新伪记录”部分

标签: sql oracle plsql triggers oracle19c


【解决方案1】:
  1. 在创建触发器时,您不能仅从表 Borrwo 使用其他表中的旧值和新值

  2. 您需要在WHEN子句中指定是否要检查新值或旧值

    CREATE OR REPLACE TRIGGER "AUDIT_TRIGGER"
    BEFORE INSERT OR UPDATE ON Borrow --I have removed double quotes
    FOR EACH ROW
    WHEN (new.Cus_evo = 0) -- I have added new. before the name of the column
      BEGIN
         INSERT INTO Audit_Table
         VALUES (:OLD.Fee, :OLD.Copy_id, :OLD.Cus_id, :OLD.B_Date, :OLD.Cus_evo);
         -- I have replaced column names from other tables with column names 
         -- from table "Borrow"
    END;
    /
    

这是一个演示:

DEMO

在这个演示中我删除了

CONSTRAINT fk_Borrow_Copy_id_FK FOREIGN KEY (Copy_id) REFERENCES Copy(Copy_id),

来自表借用规范,因为它引用了我们在您的问题中没有的表副本。

在阅读了@Belayer 的评论后,我得出结论,您将需要两个这样的触发器:

CREATE OR REPLACE TRIGGER "AUDIT_TRIGGER"
BEFORE INSERT ON Borrow
FOR EACH ROW
when (new.Cus_evo = 0) 
BEGIN
    INSERT INTO Audit_Table
    VALUES (:new.Copy_id, :new.Copy_id, :new.B_Date, :new.Cus_id, :new.Cus_evo);
END;
/

CREATE OR REPLACE TRIGGER "AUDIT_TRIGGER2"
BEFORE UPDATE ON Borrow
FOR EACH ROW
when (OLD.Cus_evo = 0) 
BEGIN
    INSERT INTO Audit_Table
    VALUES (:OLD.Copy_id, :OLD.Copy_id, :OLD.B_Date, :OLD.Cus_id, :OLD.Cus_evo);
END;
/

这是一个带有演示的演示:

DEMO

【讨论】:

  • 嗨@Belayer,谢谢你的评论,我已经更新了你的asnwer。
  • 嗨@TharinduChathuranga,这个答案对你有帮助吗?
  • 我更新了问题,你能重新检查一下吗?
  • 嗨@TharinduChathuranga 首先分析我的答案。您不能使用 :OLD.Cus_Name 因为它是表 Audit_Table 中的列,并且您只能使用要为其构建触发器的表中的旧值。另外,请阅读 Balayer 的评论。再次,阅读我的全部答案......
猜你喜欢
  • 2021-05-23
  • 2014-04-19
  • 2012-08-14
  • 2017-10-08
  • 2021-09-05
  • 2021-06-05
  • 2018-11-03
  • 1970-01-01
相关资源
最近更新 更多