1.觸發器概述
觸發器是SQL Server數據庫應用中一個重要工具,是一種特殊類型的存儲過程,應用非常廣泛。一般存儲過程主要通過存儲過程名而被直接調用,觸發器則是通過事件觸發執行。觸發器基於一個表來創建並和一個或多個數據修改操作(插入、更新或刪除)相關聯,可視作表的一部分。觸發器與數據庫中的表緊密相關,比如當對表執行INSERT、UPDATE或DELETE操作時,觸發器就會自動執行。
SQL Server 包括兩大類觸發器:DML 觸發器和 DDL 觸發器。其中DDL 觸發器是 SQL Server 2005 的新增功能,當服務器或數據庫中發生數據定義語言 (DDL) 事件時將調用該觸發器;DML 觸發器是指當數據庫中發生數據操作語言 (DML) 事件時被調用。DML 事件包括在指定表或視圖中修改數據的 INSERT、UPDATE或 DELETE 語句。DML 觸發器可以查詢其他表,還可以包含復雜的 Transact-SQL 語句。DML 觸發器用於在數據被修改時強制執行業務規則,以及擴展 Microsoft SQL Server 2005 約束、默認值和規則的完整性檢查邏輯。本文中所講述的觸發器主要是指DML 觸發器。
DML觸發器包括三種類型:AFTER 觸發器、INSTEAD OF 觸發器、CLR 觸發器。在執行了 INSERT、UPDATE 或 DELETE 語句操作之後將會執行 AFTER 觸發器,本文將以AFTER觸發器為例來講述觸發器在保持數據完整性中的應用。其創建語法如下:
CREATE TRIGGER trigger_name
ON table_name
AFTER {[INSERT][,][UPDATE][,][DELETE]}}
AS
Sql_statements
[RETURN]
在觸發器的應用中,我們通常會用到兩個特殊的表:inserted表和deleted表。它們都是針對當前觸發器的局部表。這兩個表與觸發器所在表的結構完全相同,而且總是存儲在高速緩存中。當觸發DELETE觸發器後,從受影響的表中刪除的行的副本將被放置到deleted表中。同理當觸發INSERT觸發器後,inserted表中保存的是剛被插入的數據行的一個副本。
當一個觸發器執行激發另一個觸發器的操作,而另一個觸發器又激發第三個觸發器,如此等等,這時就發生了觸發器的嵌套。也就是下文中用到的嵌套觸發器。DML 觸發器和 DDL 觸發器最多可以嵌套 32 層。
2.1.觸發器的應用
我們以BBS論壇數據庫中多個關聯表的操作為例,闡述觸發器在保持數據完整性、一致性中的應用。
在BBS的程序設計中,我們經常會碰到對一個數據表操作的同時,還要自動對另外幾個相關聯的數據表進行操作,以保證各數據表之間數據的完整性與一致性。BBS論壇中常用的數據表有:
BBS_User表(存儲用戶信息):用於存儲用戶信息。字段有用戶名、密碼、積分、發帖數、等級ID、最後一次發帖、QQ、Email、頭像、注冊時間等;
BBS_Type表:用於存儲大版塊信息。字段有版塊ID、版塊名稱等;
BBS_LanMu表:存儲分論壇信息。字段有分論壇ID、名稱、所屬大版塊ID、主題總數、回復總數、版主等;
BBS_Topic表:存儲帖子信息。字段有帖子ID、標題、內容、發帖人、所屬分論壇ID、回復總數、點擊總數、最後一次回貼時間、回帖人等;
BBS_Reply表:存儲回復信息。字段有回復內容、回復人、回復的帖子ID、回復時間等。
在BBS論壇中,觸發器主要應用於以下幾種情況:
當用戶在分論壇裡發表帖子時,對BBS_Topic表進行操作,但同時要自動對分論壇表BBS_LanMu裡面的論壇主題總數增1,還要更新BBS_User表給該用戶增加相應的積分,當用戶積分達到一定分數時,自動更新該用戶的等級ID,表示該用戶已經升了一個等級。
當用戶回復帖子時,對BBS_Reply表操作的同時,也需要對分論壇表BBS_LanMu裡的回復總數增1、對BBS_Topic表的回復總數增1並更新該表裡的最後回帖標題和時間,還要將BBS_User表裡的該用戶的發帖數增1、自動增加相應積分、更新最後發帖標題和時間等;
在論壇的後台管理中,管理員有時需要添加或者刪除一個大版塊。當我們要刪除BBS_Type表一個大版塊時,為了保證數據庫各表中數據的完整性與一致性,要同時對BBS_LanMu表、BBS_Topic表、BBS_Reply表中相關聯的數據記錄一並刪除。
下面將以後台管理中對論壇大版塊進行刪除操作時應用觸發器為例來進行具體介紹。
(1) 需求分析
在一個論壇中有許多個大版塊,每個版塊又對應多個分論壇。每個論壇又對應多個帖子,每個帖子又對應多個回復信息。因此需要4個相關聯的表來存儲相應的信息:BBS_Type表(存儲大版塊信息)、BBS_LanMu表(存儲分論壇信息)、BBS_Topic表(存儲帖子信息)、BBS_Reply表(存儲回復信息)。BBS_Type與BBS_LanMu、BBS_LanMu與BBS_Topic、BBS_Topic與BBS_Reply之間都是一對多的關系。
當我們要刪除BBS_Type表一個大版塊時,為了保證數據庫各表中數據的完整性與一致性,需要同時對BBS_LanMu表、BBS_Topic表、BBS_Reply表中相關聯的數據記錄一並刪除。因為這裡面存在3對一對多的關系,如果在程序中或者存儲過程實現,顯然是很困難也是不合理的。根據觸發器的作用以及這4個表之間的關系,采用嵌套觸發器來實現這個刪除功能。為BBS_Type表、BBS_LanMu表、BBS_Topic表分別建立一個AFTER觸發器,該觸發器由DELETE事件觸發。采用嵌套觸發器可以在數據庫裡自動完成這多個表中相關記錄的刪除,大大簡化了業務邏輯。這樣即保證了數據的完整性與一致性,又保證程序設計的合理性與方便性。
(2)創建觸發器
根據需求分析,為BBS_Type表、BBS_LanMu表、BBS_Topic表分別建立AFTER觸發器,該觸發器由DELETE事件觸發。建立在這3個表之上的觸發器之間是嵌套觸發的關系,即BBS_Type表上的觸發器觸發BBS_LanMu表上的觸發器,BBS_LanMu表上的觸發器再觸發BBS_Topic表上的觸發器。本文中使用的數據庫為Microsoft SQL Server 2005。要讓觸發器能嵌套觸發必須在數據庫“屬性”中,將“遞歸觸發器已啟用”設置為TRUE。
1.為BBS_Type表(存儲大版塊信息)建立觸發器DelType。該觸發器功能是刪除BBS_LanMu表中屬於剛刪除的大版塊的所有分論壇信息。
CREATE trigger [DelType] on [dbo]。[BBS_Type]
after delete
as
begin
declare @typeid int
select @typeid=TypeID from deleted --獲得要被刪除的版塊ID
delete from dbo.BBS_LanMu where Typeid=@typeid
end
2.為BBS_LanMu表(存儲分論壇信息)建立觸發器DelLanmu。該觸發器功能是刪除BBS_Topic表中屬於剛刪除分論壇的所有帖子信息。
CREATE trigger [DelLanmu] on [dbo]。[BBS_LanMu]
AFTER DELETE
as
BEGIN
declare @lmid int
select @lmid=LMID from deleted --獲得要被刪除的分論壇ID
delete from dbo.BBS_Topic where LMID=@lmid
END
3.為BBS_Topic表(存儲帖子信息)建立觸發器DelTopic。該觸發器功能是刪除BBS_Reply表中屬於剛刪除帖子的所有回復信息。
CREATE trigger [DelTopic] on [dbo]。[BBS_Topic]
after delete
as
BEGIN
declare @tid int
select @tid=TID from deleted --獲得要被刪除的帖子ID
delete from dbo.BBS_Reply where TID=@tid
END
執行過程
當數據操作層對數據表BBS_Type發出DELETE一條記錄的時候,觸發器DelType被觸發,此觸發器將刪除BBS_LanMu表中屬於剛刪除的大版塊的所有分論壇信息。
當DelType觸發器對數據表BBS_LanMu刪除一條記錄時,又觸發BBS_LanMu表上的觸發器DelLanmu,此觸發器將刪除BBS_Topic表中屬於剛刪除分論壇的所有帖子信息。
當DelLanmu觸發器對數據表BBS_Topic刪除一條記錄時,又觸發觸發器DelTopic,此觸發器將刪除BBS_Reply表中屬於剛刪除帖子的所有回復信息。
至此數據庫中與BBS_Type中刪除記錄相關聯的所有記錄全部刪除,保證了數據庫各表數據的完整性與一致性。這個過程是在數據庫中自動進行的,因此速度非常快,用戶只需要對BBS_Type表發出刪除一條記錄的命令,其他表中相關的記錄會自動刪除。
3.1.總結:
觸發器能保持數據的完整性與一致性,它可以方便地基於一個表的修改,自動更新其他相關表的記錄,以保證數據的完整性。在數據庫的應用中,觸發器扮演著很重要的角色。無論是作為提供高級參照完整性功能的途徑,還是執行自動維護非正規化數據的任務,觸發器都能幫助用戶實現滿足實際需要的規則,簡化業務邏輯,並使系統更方便更有效。