觸發(fā)器(Trigger)是用戶定義在關系表上的一類由事件驅動的特殊過程。一旦定義,任何用戶對表的增、刪、改操作均由服務器自動激活相應的觸發(fā)器。它類似于約束,但是比約束更加靈活,并且可以實施比FOREIGN KEY(外鍵)約束、CHECK約束更為復雜的檢查和操作,具有更精細和更強大的數(shù)據(jù)控制能力。
下面是觸發(fā)器一些特性:
1、 表的創(chuàng)建者才可以在表上創(chuàng)建觸發(fā)器,并且一個表上只能創(chuàng)建一定數(shù)量的觸發(fā)器;
2、 觸發(fā)器名可以包含模式名,也可以不包含。但是在同一模式下,觸發(fā)器必須是唯一的,并且觸發(fā)器名和表名必須在同一模式下;
3、 當某個表的數(shù)據(jù)發(fā)生變化時,將激活定義在該表上相應的“觸發(fā)事件”的觸發(fā)器,因此,該表也稱為觸發(fā)器的目標表;
4、 觸發(fā)事件可以是單獨的操作(增、刪、改)或幾個操作的組合,如INSERT OR DELETE等。而且UPDATE后邊還可以有OF<觸發(fā)列,…..>,即進一步指明修改哪些列時激活觸發(fā)器;
5、 觸發(fā)器的類型,按所觸發(fā)動作的間隔尺寸可以分為行級觸發(fā)器(FOR EACH ROW)和語句級觸發(fā)器(FOR EACH STATEMENT)。對于什么叫“間隔尺寸”,書面上比較難理解,那么看以下的例子:
例:假設有個職工工資表WORKER,要求每個職工的應發(fā)工資不能低于3000元。那么如果在這個表上創(chuàng)建了一個AFTER UPDATE觸發(fā)器,且該表有1000行記錄,執(zhí)行如下語句:
UPDATE WORKER SET Deptno=5;
如果改觸發(fā)器為語句級觸發(fā)器,那么執(zhí)行完該語句后,觸發(fā)動作只發(fā)生一次。如果是行級觸發(fā)器,觸發(fā)動作將執(zhí)行將執(zhí)行1000次;
6、 觸發(fā)條件,當觸發(fā)器被激活時,只有當觸發(fā)條件為真時觸發(fā)動作體才執(zhí)行。如果省略WHEN觸發(fā)條件,則觸發(fā)動作體在觸發(fā)器被激活后無條件執(zhí)行;
7、 觸發(fā)動作體既可以是一個匿名PL/SQL過程塊,也可以是對已創(chuàng)建存儲過程的調用。如果是行級觸發(fā)器,在兩種情況下,用戶都能在過程體中使用NEW和OLD引用UPDATE/INSERT事件之后的新值和UPDATE/INSERT事件之后的舊值。如果是語句級觸發(fā)器,則不能在觸發(fā)動作體中使用NEW或OLD進行引用。
如果觸發(fā)動作體執(zhí)行失敗,激活觸發(fā)器的事件就會終止執(zhí)行,觸發(fā)器的目標表或觸發(fā)器可能影響的其他對象不會發(fā)生任何變化。
以下是兩個個經典的觸發(fā)器例子:
例1:定義一個BEFORE行級觸發(fā)器,為職工表WORKER定義完整性規(guī)則“管理人員工資不能低于4000元,如果低于4000元,自動改為4000元”。
CREATE TRIGGER insert_Or_Updatee_Sal /*在WORKER表中定義觸發(fā)器*/
BEFORE INSERT OR UPDATE ON WORKER /* 觸發(fā)事件是插入或更新操作*/
FOR EACH ROW /*表示行級觸發(fā)器*/
AS BEGIN /*定義觸發(fā)器動作體,這是一個PL/SQL過程塊*/
IF(new.Job=’管理人員’)AND(new.Sal<4000)THEN /*因為是行級觸發(fā)器*/
new.Sal := 4000; /*過程體中使用插入或更新操作后的新值*/
END IF;
END;
例2:定AFFTER行級觸發(fā)器,當員工表WORKER的工資發(fā)生變化后就自動在工資變化表Sal_log中增加一條記錄。
首先建立工資變化表Sal_log:
CREATE TABLE Sal_log
(Eno NUMERIC(4) REFERENCES WORKER(Eno),
Sal NUMERIC(7,2),
Username char(10),
Date TIMESTAMP
);
CREATE TRIGGER Insert _Sal
AFTER INSERT ON WOEKER
FOR EACH ROW
AS BEGIN
INSERT INTO Sal_log VALUES(
new.Eno,new.Sal,CURRENT_USER,CURRENT_TIMESTAMP);
END;
CREATE TRIGGER Update _Sal
AFTER INSERT ON WOEKER
FOR EACH ROW
AS BEGIN
IF(new.Sal<>old.Sal) THEN INSERT INTO Sal_log VALUES(
new.Eno,new.Sal,CURRENT_USER,CURRENT_TIMESTAMP);
END IF;
END;
聯(lián)系客服