基於SQL SERVER觸發器技術的實現

在數據庫管理系統中,如何保證數據庫中的數據完整性是一項重要的課題。數據完整性是指存儲在數據庫的數據的一致性。主要體現在以下幾個方面:實體完整性(Entity Integrity)、域完整性(Domain Integrity)、參照完整性(Referential Integrity)和用戶的自定義完整性(User define Integrity)。目前,已有多種方法來解決這個問題。從最基本的數據類型,到多種形式的約束條件,雖然都提出了數據完整性的解決方案,但由於這些方法較爲簡單,不能解決比較複雜的數據完整性問題。而觸發器(Trigger)作爲一種高級的技術,可以輕鬆地解決任何有關保證數據完整性的問題。
一、在SQL SERVER環境中使用觸發器
   1觸發器的工作原理
觸發器是一種特殊類型的存儲過程,它與表緊密聯繫在一起,在對錶進行插入、刪除和更新時,如該表(也稱觸發器表)有相應操作類型的觸發器,則觸發器便會自動觸發執行。觸發器分爲INSERT觸發器、DELETE觸發器和UPDATE觸發器3類。當向觸發器表中插入數據時,INSERT觸發器將觸發執行,新的記錄會增加到觸發器表和inseted表中;當刪除觸發器表中的數據時,DELETE觸發器將觸發執行,被刪除的記錄會存放到deleted表中;當更新觸發器表中的數據時,相當於插入一條新記錄和刪除一條舊記錄,此時UPDATE觸發器將觸發執行,表中原有的記錄存放到deleted表中,修改後的記錄插入到inserted表中。其中inserted表和deleted表是兩個邏輯表,由系統來維護,不允許用戶直接對這兩個表進行修改。它們存放於內存中,不存放在數據庫中。這兩個表的結構總是與被該觸發器作用的表的結構相同。觸發器工作完成後,與該觸發器相關的這兩個表也會被刪除。deleted表用於存儲SQL語言中DELETE和UPDATE語句所影響的行的複本。在執行DELETE或 UPDATE語句時,行從觸發器表中刪除,並傳輸到 deleted 表中。deleted 表和觸發器表通常沒有相同的行;inserted 表用於存儲 SQL語言中INSERT 和 UPDATE 語句所影響的行的副本。在一個插入或更新事務處理中,新建行被同時添加到 inserted 表和觸發器表中。inserted 表中的行是觸發器表中新行的副本。
  2觸發器的實現步驟
在筆者開發的教材管理系統中,建立了一個教材數據庫JCSJK,其中有教材表JCB和教材進出明細表MXB,需要在對MXB進行插入、刪除和修改時,動態地修改JCB中對應教材的庫存數量。下面舉例說明觸發器的實現步驟。爲減少篇幅,對錶結構作了簡化處理。以下操作在Microsoft SQL SERVER環境中完成。
  (1)建立教材表JCB,並定義主鍵
CREATE TABLE [dbo].[JCB] (
[教材代碼] [char] (10) NOT NULL ,
[教材名] [char] (30) NOT NULL ,
[價格] [decimal](18, 2) NOT NULL ,
[庫存量] [int] NULL ,
[出版社] [char] (20) NULL 
) ON [PRIMARY]ALTER TABLE [dbo].[JCB] WITH NOCHECK ADD
CONSTRAINT [PK-JCB] PRIMARY KEY CLUSTERED
([教材代碼]
) ON [PRIMARY]
  (2)建立教材進出明細表MXB,並定義主鍵和外?br> CREATE TABLE [dbo].[MXB] (
[教材代碼] [char] (10) NOT NULL ,
[日期] [datetime] NOT NULL ,
[教材進] [int] NULL ,
[教材出] [int] NULL ,
[備註] [char] (40) NULL 
) ON [PRIMARY]
ALTER TABLE [dbo].[MXB] WITH NOCHECK ADD
CONSTRAINT [PK-MXB] PRIMARY KEY CLUSTERED 
([教材代碼],
[日期]
) ON [PRIMARY]
ALTER TABLE [dbo].[MXB] ADD
CONSTRAINT [FK-MXB-JCB] FOREIGN KEY
([教材代碼]) REFERENCES [dbo].[JCB] (
[教材代碼]) ON DELETE CASCADE ON UPDATE CASCADE
圖1顯示了JCB和MXB兩個表的關係。


  (3)在MXB上建立INSERT觸發器
CREATE TRIGGER MXB-INSE ON [dbo].[MXB]
FOR INSERT
ASUPDATE JCB SET 庫存量=庫存量+
(SELECT 教材進-教材出 FROM INSERTED)
FROM JCB,INSERTEDWHERE JCB.教材代碼=INSERTED.教材代碼
(4)在MXB上建立DELETE觸發器
CREATE TRIGGER MXB-DELE ON [dbo].[MXB]
FOR DELETE
AS
UPDATE JCB SET 庫存量=庫存量-
(SELECT 教材進-教材出 FROM DELETED)
FROM JCB,DELETEDWHERE JCB.教材代碼=DELETED.教材代碼〖HT〗
  (5)在MXB上建立UPDATE觸發器
CREATE TRIGGER MXB-UPDA ON [dbo].[MXB]
FOR UPDATE
AS
BEGINUPDATE JCB SET 庫存量=庫存量-
(SELECT 教材進-教材出 FROM DELETED)
FROM JCB,DELETED
WHERE JCB.教材代碼=DELETED.教材代碼
UPDATE JCB SET 庫存量=庫存量+
(SELECT 教材進-教材出 FROM INSERTED)
FROM JCB,INSERTEDWHERE JCB.教材代碼=INSERTED.教材代碼
END
  通過以上步驟,設置了MXB表的3類觸發器,當用戶對MXB表進行插入、刪除和修改時,將根據MXB中教材進出的情況動態地修改JCB中對應教材的庫存量。由於在觸發器中,涉及到的inserted表和deleted表均存放在內存中,因此,觸發器的執行速度較快。
  3設計觸發器的考慮
  在寫觸發器代碼時需要考慮的一個重要問題就是,引發觸發器的語句可以是一個影響單行的語句,也可以是一個影響多行的語句。這在 UPDATE 和DELETE 觸發器中很常見,因爲這些語句經常作用於多行。而這在 INSERT 觸發器中就比較少見,因爲基本的 INSERT 語句只添加一行。然而,由於 INSERT 觸發器可由 INSERT INTO (table_name) SELECT 語句激發,所以,插入許多行可能導致單個的觸發器調用。上面討論的涉及MXB的3類觸發器都是針對影響單行的語句。因此,有必要考慮影響多行的語句,這裏對MXB的INSERT觸發器進行討論。
  (1)可處理多行的MXB上的INSERT觸發器
  如果要進行多行插入,上面示例中的觸發器可能就不能正確處理,因爲 UPDATE 語句賦值表達式右邊的表達式只能是一個值,而不能是一個值列表。因此,該觸發器的作用就是獲取 inserted 表中任意一行的值,並將其添加到JCB表中特定教材代碼值的已有庫存量值上。如果某個教材代碼值在inserted 表中出現了多次,則可能無法得到預期的結果。爲了正確地更新JCB表,觸發器就必須適應inserted表中出現多行的可能性。這可以通過 SUM 函數實現,它爲 inserted 表中每個教材代碼計算教材進出的總計。SUM 函數存放於相關子查詢中(SELECT 語句在括號內)。該子查詢爲 inserted 表中與JCB表的教材代碼匹配或相關的每個教材代碼返回一個單一值。
CREATE TRIGGER MXB-INSE ON [dbo].[MXB]
FOR INSERT
AS
UPDATE JCB SET 庫存量=庫存量+
(SELECT SUM(教材進-教材出) FROM INSERTED
WHERE JCB.教材代碼=INSERTED.教材代碼)
WHERE JCB.教材代碼 IN
(SELECT 教材代碼 FROM INSERTED)
  該觸發器對單行插入同樣適用,不過,使用該觸發器時,WHERE 子句中所使用的相關子查詢和 IN 運算符需要額外處理,而這對於單行插入來說是不必要的。
  (2)可區分單行和多行插入的MXB上的INSERT觸發器可以通過系統函數@@ROWCOUNT以區分單行插入和多行插入,以使觸發器針對不同行數使用最優方法。
CREATE TRIGGER MXB_INSE ON [dbo].[MXB]
FOR INSERT
AS
IF @@ROWCOUNT=1
BEGIN
UPDATE JCB SET 庫存量=庫存量+
(SELECT 教材進-教材出 FROM INSERTED)
FROM JCB,INSERTED
WHERE JCB.教材代碼=INSERTED.教材代碼
END
ELSE
BEGIN
UPDATE JCB SET 庫存量=庫存量+
(SELECT SUM(教材進-教材出) FROM INSERTED
WHERE JCB.教材代碼=INSERTED.教材代碼)
WHERE JCB.教材代碼 IN
(SELECT 教材代碼 FROM INSERTED)
END
  二、結論
  觸發器應用於支持企業級商業解決方案時,是一個功能十分強大的工具。它可以用於實現業務規則,可以檢查事務,可以在同一表上創建多個觸發器來分離代碼的功能。另外,通過使用觸發器收集的信息,可以提高數據庫的性能,可以用來維護那些使用外鍵所不能實現的複雜參數完整性。因此,對於維護數據表之間一致性,保持數據的相關完整性的情況,觸發器應作爲首先考慮的技術。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章