觸發器

目錄

一、觸發器的主要優點

二、觸發器支持的功能

三、觸發器的類別

四、SQL Server中觸發器的創建、刪除和修改 

4.1創建觸發器的語句

4.2刪除和修改觸發器

4.3觸發器中可使用的特殊表(inserted表和deleted表)

 五、 觸發器應用舉例

5.1INSERT 觸發器

5.2 DELETE觸發器

5.3 UPDATE觸發器 

六、使用觸發器的考慮


 

  觸發器(Trigger)不僅能實現完整性規則,而且能保證一些較複雜業務規則的實施。  

        所謂觸發器就是一類由事件驅動的特殊過程(特殊類型的存儲過程),當一個觸發器建立後,它作爲一個數據庫對象被存儲。當某個觸發事件發生時,觸發器被觸發,執行一系列操作。  

        觸發器一旦由某個用戶建立,任何用戶對該觸發器指定的數據進行增、刪或改操作時,DBMS系統將自動激活相應的觸發器,定義在觸發器中的功能將被DBMS執行,在覈心層進行集中的完整性控制。

        觸發器使用戶定義在關係表上的一類由事件驅動的特殊過程。一旦定義就被保存在數據庫服務器中。觸發器類似於約束,單是比約束更加靈活,可以實施更爲複雜的檢查和操作,具有更精細和更強大的數據控制能力。

 

一、觸發器的主要優點

觸發器的主要優點 
 ⑴ 觸發器能夠實施比外鍵約束,檢查約束和規則對象 
    等更爲複雜的數據完整性檢查。
 ⑵ 和約束相比,觸發器提供了更多的靈活性。約束將
    系統錯誤信息返回給用戶,而觸發器可以打印錯誤   
    信息,調用其他存儲過程,或根據需要糾正錯誤。
 ⑶ 無論對錶中的數據進行何種更新(增刪改操作),
    相應的觸發器都能被激活,對數據實施完整性檢查
    和處理。
 ⑷ 觸發器能夠級聯更新數據庫中的表內容

 

二、觸發器支持的功能

⑴ 觸發器可以在事件之前、之後執行,還可以替代觸 
    發語句的操作。例如可以定義觸發器在對某關係執
    行INSERT、 UPDATE和DELETE操作之前後觸發。
⑵ 觸發器有語句級觸發器和行級觸發器之分。對被事 
    件影響修改的每一行(FOR EACH ROW)即每一元組
    執行一次觸發過程,稱爲行級觸發器。對整個事件     
    只執行一次觸發過程(FOR EACH STATEMENT),稱
    爲語句級觸發器,該方式是觸發器的默認方式。
⑶ 對於UPDATE事件可以定義對哪個關係、或關係
    中的哪一列修改時,觸發器觸發。
⑷ 可以指定執行條件,當觸發器被觸發後,觸發器
    功能代碼只有在條件成立時才執行。
⑸ 觸發器代碼可以引用事件中對於元組修改前後的值(OLD值和NEW值)。
⑹ 觸發器可以完成一些複雜的數據檢查,可以實現某些操作的前後處理等。
⑺ 觸發器定義的約束可以在任何顆粒級別上實現、表示動態的或靜態的約
    束、延遲或不延遲進行觸發檢查、可以用SQL語句定義約束觸發器的功能。

 

三、觸發器的類別

⑴ 按觸發事件分:有INSERT觸發器、 UPDATE觸發器和DELETE觸發器之分。
⑵ 按觸發時間分:有BEFORE觸發器和AFTER觸發器之分。
                              BEFORE觸發器是在事件發生之前觸發,AFTER觸發器是在事件發生之後觸發。
⑶ 按觸發方式分:有語句級觸發器和行級觸發器之分。
   注:SQL Server 對上述部分功能可實現,但在語法描述上有區別。

四、SQL Server中觸發器的創建、刪除和修改 

觸發器的定義包括兩個方面:指明觸發器的觸發事件指明觸發器執行的動作

4.1創建觸發器的語句

創建觸發器的語句一般格式爲:

CREATE TRIGGER <觸發器名> ON {<表名>|<視圖名>} 
  [WITH ENCRYPTION] 
  FOR {[INSERT][,][UPDATA][,][DELETE]}
AS 
T-SQL語句序列 

說明:
① 表名,視圖名:爲觸發該觸發器的表名或視圖名。  
   SQL Server中,只有表的所有者纔有權建立觸發器。
② INSERT,UPDATA,DELETE :說明觸發觸發器的事件。
                                                    一個定義語句允許定義多個觸發事件,用逗號分開。
③ WITH ENCRYPTION:該選項對觸發器定義文本加密。
④ T-SQL操作語句序列:指定觸發器動作。該語句中可以指定多個觸發器操作,
                                        這時要用BEGIN…END將它們組成語句塊。

 

4.2刪除和修改觸發器

(1)刪除觸發表時,觸發器被隨之刪除。
(2)可以用DROP語句刪除已定義的觸發器。
    也可以使用ALTER TRIGGER語句修改觸發器定義。
例如,刪除已定義觸發器的語句格式:
 DROP TRIGGER <觸發器名> [,<觸發器名>…]

 

4.3觸發器中可使用的特殊表(inserted表和deleted表)

使用觸發器時,SQL Server提供了兩張特殊的臨時表:
    inserted表和deleted表
    這兩張表存在於高速緩存中,它們與創建觸發器的表有相同的結構。
    用戶可以使用該表檢查某些修改操作的效果。
    但用戶不能直接修改該表中的數據。
    用戶可以使用該表的內容作爲查詢操作的判斷條件,但要在FROM中寫出使用的表名(inserted或deleted)。 
 

① inserted表:
    存放被INSERTE插入和UPDATE更新的新數據。當向表中插入數據時,INSERT觸發器被觸發。新的記錄增加到觸發器表中和inserted表中。  
    inserted表是一個邏輯表,保存了所插入記錄的拷貝,觸發器可以檢查inserted表,來確定該觸發器的操作是否應該執行和如何執行。

② deleted表:
    存放被DELETE刪除和UPDATE更新的舊數據。
    當觸發一個DELETE觸發器時,被刪除的記錄放在一個特殊的deleted表中。
    deleted表是一個邏輯表,用來保存已經從表中刪除的記錄。DELETE觸發器可以參考deleted表中的數據。

注:
   UPDATE觸發器可使用deleted表和inserted表修改一條記錄等於刪除一條舊記錄和插入一條新記錄。
   UPDATE可以看成是由DELETE語句和 INSERT 語句組成。當在一個有UPDATE觸發器的表上修改一條記
   錄時,表中原來的記錄移動到deleted表中,修改過的記錄插入到inserted表中。UPDATE觸發器可以
   參考deleted表和inserted表,以便確定如何執行觸發器的操作。

 

 五、 觸發器應用舉例

創建觸發器的語句一般格式爲:

CREATE TRIGGER <觸發器名> ON {<表名>|<視圖名>} 
  [WITH ENCRYPTION] 
  FOR {[INSERT][,][UPDATA][,][DELETE]}
AS 
T-SQL語句序列 

 

假設學生表S新增一屬性Cnum(類型爲INT,初值均爲0), 記錄該學生的選課數,分別創建如下觸發器:

5.1INSERT 觸發器

例1.創建INSERT 觸發器Tri1,其功能是:在學習表SC插入一條記錄後,立即更新學生表S的Cnum屬性,即將原值加一

 CREATE TRIGGER Tri1 ON SC FOR INSERT
     AS
     UPDATE Student SET Cnum=Cnum+1
     WHERE Student.Sno=(SELECT Sno FROM inserted WHERE Student.Sno=inserted.Sno)

執行:

go
create trigger tri1 on Cj for insert
	as
	update Student set Cnum=Cnum+1
	where Student.sno=(select Sno from inserted where Student.Sno=inserted.Sno)
go

insert into Cj values(2000101,1,92);
-- 運行結果:
(1 行受影響)

(1 行受影響) -- 也影響了student表的一行


go -- 存儲過程
create procedure fs
as select * from Student;

exec fs;
運行結果:
2000101	李勇      	男	20	00311	1  --果然Cnum也加1了
2000102	劉詩晨    	女	19	00311	0

 

 

5.2 DELETE觸發器

例9.創建DELETE觸發器Tri2,其功能是:在刪除學習表SC一條記錄後,立即更新學生表S的Cnum屬性,即將原值減一.

CREATE TRIGGER Tri2 ON SC FOR DELETE
     AS
       UPDATE Student SET Cnum=Cnum-1
       WHERE Student.Sno=(SELECT Sno FROM deleted WHERE Student.Sno=deleted.Sno) 

執行過程:

go
create trigger tri2 on Cj for delete
	as
	update Student set Cnum=Cnum-1
	where Student.Sno=(Select Sno from deleted where Student.Sno=deleted.Sno);
-- 命令已成功完成。

delete Cj where Sno='2000101' and Cno='1';
-- 運行結果
(1 行受影響)
(1 行受影響) -- 說明影響2行

exec fc;
exec fs;
-- 運行結果: 
2000101	李勇      	男	20	00311	0 -- Cnum果然減1了
2000102	劉詩晨    	女	19	00311	0

 

 

5.3 UPDATE觸發器 

例10 創建UPDATE 觸發器Tri3,功能是:在SC表更新一條記錄的學號後,立即更新學
     生表S的Cnum屬性,改前學號學生的Cnum值減1,改後學號學生的Cnum值加1。

go
create trigger tri3 on Cj for update
	as
	    if update(Sno)
		begin
			update Student set Cnum=Cnum-1
				where Sno=(select Sno from deleted where deleted.Sno=Student.Sno);
			update Student set Cnum=Cnum+1
				where Sno=(select Sno from inserted where inserted.Sno=Student.Sno);
		end

執行過程:

go
create trigger tri3 on Cj for update
	as
	    if update(Sno) -- 不可少 不然修改一下grade的值Sno並未刪除 也會執行下面明顯不合理
		begin
			update Student set Cnum=Cnum-1
				where Sno=(select Sno from deleted where deleted.Sno=Student.Sno);
			update Student set Cnum=Cnum+1
				where Sno=(select Sno from inserted where inserted.Sno=Student.Sno);
		end

insert into Cj values(2000101,1,92);
exec fs;
exec fc;

update Cj set Sno=2000103 where Sno=2000101;
運行結果:
(1 行受影響)

(0 行受影響)

(1 行受影響)
--說明確實進行了3次操作


注:if update(Sno)有了此句:
     只有改Sno的值纔會觸發觸發器  改其他值不會(運行結果僅一行)

 

 

六、使用觸發器的考慮

觸發器最大的用途是維護數據完整性,而不是返回結果。

只是在必要的時候使用觸發器。如果使用約束、規則,
默認就可以實現預定的數據完整性時,應優先考慮使用這3種措施

使觸發器的定義語句儘可能清晰簡單。

觸發器一般定義在操作發生之後執行,約束在操作發生之前起作用。如果在觸發器表上有約
束,那麼這些約束在觸發器執行之前進行檢查。如果操作與約束有衝突,那麼觸發器不執行。

有的DBMS系統的觸發器不能在臨時表或視圖上創建,但可以參照這些對象。

觸發器和激活它的語句作爲單個事務處理,如果檢查到嚴重錯誤,整個事務自動撤銷。 
 

 

附錄:

-- 觸發器
create database Trig;
use Trig;

create table Student(
	Sno Char(7) primary key,--學號
	Sname Char(10) not null,--學生姓名
	Ssex Char(2) check(Ssex in('男','女')) default '男'not null,--性別
	Sage Smallint check(Sage>14 and Sage<65),--年齡
	Clno Char(5) not null,--學生所在班級號
	Cnum int default 0 -- 選課數
); 

create table Cj(
	Sno Char(7),--學號
	Cno Char(1),--課程號
	Grade Decimal(4,1) check(Grade>0 and Grade<100),--成績
	primary key(Sno,Cno)
);


-- 預備語句
insert into Student values(2000101,'李勇','男',20,'00311',0);--漢字字符型必須''
insert into Student values(2000102,'劉詩晨','女','19','00311',0);--int型可以傳遞字符串(不打'')
select * from Student;

select * from Cj;
insert into Cj values(2000101,1,92);


-- 往Cj表新增一條記錄  對Studnet表相應學號的學生Cnum+1(選課數+1)
go
create trigger tri1 on Cj for insert
	as
	update Student set Cnum=Cnum+1
	where Student.sno=(select Sno from inserted where Student.Sno=inserted.Sno)


go
create procedure fs
as select * from Student;
--也ok
go
create procedure fc
as select * from Cj;

exec fs



-- delete
go
create trigger tri2 on Cj for delete
	as
	update Student set Cnum=Cnum-1
	where Student.Sno=(Select Sno from deleted where Student.Sno=deleted.Sno);
-- 命令已成功完成。
delete Cj where Sno='2000101' and Cno='1';
-- 運行結果
(1 行受影響)
(1 行受影響)

exec fc;
exec fs;


-- update
go
create trigger tri3 on Cj for update
	as
	    if update(Sno)
		begin
			update Student set Cnum=Cnum-1
				where Sno=(select Sno from deleted where deleted.Sno=Student.Sno);
			update Student set Cnum=Cnum+1
				where Sno=(select Sno from inserted where inserted.Sno=Student.Sno);
		end



insert into Cj values(2000101,1,92);
exec fs;
exec fc;
update Cj set Sno=2000103 where Sno=2000101;

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章