INSTEAD OF 觸發器

        Instead Of觸發器與After觸發器的工作流程是不一樣的。After觸發器是在SQL Server服務器接到執行SQL語句請求之後,先建立臨時的Inserted表和Deleted表,然後實際更改數據,最後才激活觸發器的。而Instead Of觸發器看起來就簡單多了,在SQL Server服務器接到執行SQL語句請求後,先建立臨時的Inserted表和Deleted表,然後就觸發了Instead Of觸發器,至於那個SQL語句是插入數據、更新數據還是刪除數據,就一概不管了,把執行權全權交給了Instead Of觸發器,由它去完成之後的操作。

Instead Of觸發器的使用範圍

Instead Of觸發器可以同時在數據表和視圖中使用,通常在以下幾種情況下,建議使用Instead Of觸發器:

>> 數據庫裏的數據禁止修改:例如電信部門的通話記錄是不能修改的,一旦修改,則通話費用的計數將不正確。在這個時候,就可以用Instead Of觸發器來跳過Update修改記錄的SQL語句。

>> 有可能要回滾修改的SQL語句:用After觸發器並不是一個最好的方法,如果用Instead Of觸發器,在判斷折扣大於0.6時,就中止了更新操作,避免在修改數據之後再回滾操作,減少服務器負擔。

>> 在視圖中使用觸發器:因爲After觸發器不能在視圖中使用,如果想在視圖中使用觸發器,就只能用Instead Of觸發器。

>> 用自己的方式去修改數據:如不滿意SQL直接的修改數據的方式,可用Instead Of觸發器來控制數據的修改方式和流程。

一個例子:

--創建表

CREATE TABLE [tt] (
[a] [int] NOT NULL ,
[b] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[c] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
CONSTRAINT [PK_tt] PRIMARY KEY CLUSTERED
(
   [a]
) ON [PRIMARY]
) ON [PRIMARY]
GO

--創建觸發器

CREATE TRIGGER ta ON [dbo].[tt]
INSTEAD OF INSERT
AS
SET NOCOUNT ON
if (SELECT a from inserted)>3
   print N'不能插入大於3的'
else
   insert into tt select * from inserted

--執行

INSERT INTO tt values(5,'a','aa')

select * from tt

可以看到insert語句並沒有把數據插入進去。

------------------------------------------------------------------------------------------------

雖然視圖通常不能動態修改,但是,使用 INSTEAD OF 觸發器您可以指定操作,保持視圖最新,同時修改視圖基礎基表中的數據。例如,您可在視圖上定義 INSTEAD OF INSERT 觸發器,以替換標準的 INSERT 語句。

假定在 pubs 數據庫中以下面的視圖開始:

CREATE VIEW AuthorsNames
AS
SELECT au_id, au_fname, au_lname
FROM authors

如果直接對 authors 表應用 INSERT 事件,則該視圖將是不正確的,因爲沒有向該視圖通知新插入的作者。避免此問題的方法是在該視圖上創建 INSTEAD OF 觸發器來處理插入。

CREATE TRIGGER ShowInsert on AuthorsNames
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO authors
   SELECT address, au_fname, au_id, au_lname, city, contract, phone, state, zip
   FROM inserted
END
創建結構

CREATE TRIGGER <觸發器名>

ON <表名 | 視圖名>

{FOR | AFTER | INSTEAD OF} {[INSERT] [,UPDATE] [,DELETE]}

AS

{ [IF UPDATE(列名)] [{AND | OR} UPDATE (列名)] }

收集2

DML觸發器是表上的程序,主要提供數據添加、修改與刪除後的程序處理方法,可以用來檢查數據及進行數據更新,也可以分擔一些前端應用程序撰寫的邏輯規則。
觸發器英文名爲trigger,也就是板機的意思,與槍支的操作原理類似,只有扣動板機,子彈纔會飛出。將該詞用在SQL SERVER環境中,表示當表發生了insert 、update、delete操作之後,纔會執行的t-SQL程序,這樣的程序就叫觸發器。

應用場景: 觸發器可以查詢其他表,而且可以包含複雜的SQL語句。它們主要用於強制複雜的業務規則或要求。
觸發器的主要應用場合概括起來講有以下幾種:
    1.當向一張表中添加或刪除記錄時,需要在相關表中進行同步操作。比如,當爲應用系統添加一個系統用戶時,需要同時向權限表中添加該用戶的缺省權限,此時就編寫系統用戶表的觸發器在添加記錄動作時觸發。
    2.當表上某列數據的值與其他表中的數據有聯繫時。比如,當某客戶進行欠款消費,可以在生成訂單時通過設計觸發器判斷該客戶的累計欠款是否超出了最大限度。
    3.當需要對某張表進行跟蹤時。比如,當人事表中有人離職時,第一時間通知或更改相關表的值。

DML觸發器的分類SQL Server 2005的DML觸發器分爲兩類:
        * After觸發器:這類觸發器是在記錄已經改變完之後(after),纔會被激活執行,它主要是用於記錄變更後的處理或檢查,一旦發現錯誤,也可以用Rollback Transaction語句來回滾本次的操作。
        * Instead Of觸發器:這類觸發器一般是用來取代原本的操作,在記錄變更之前發生的,它並不去執行原來SQL語句裏的操作(Insert、Update、Delete),而去執行觸發器本身所定義的操作。

應用示例:alter

 Instead Of

01 --例一:以下是一個包含提醒電子郵件的觸發器例子,如果訂單表裏記錄有改動的的話(無論增加訂單還是修改、刪除訂單),則給物流人員張三發送電子郵件:
02   
03 CREATE TRIGGER 訂單_Insert
04 ON 訂單
05 AFTER INSERT, UPDATE, DELETE
06 AS
07    EXEC master..xp_sendmail '張三', '訂單有更改,請查詢確定'
08 GO
09   
10 --例二:在訂單明細表裏,折扣字段不能大於0.6,如果插入記錄時,折扣大於0.6的話,回滾操作。
11 CREATE TRIGGER 訂單明細_Insert
12    ON  訂單明細
13    AFTER INSERT
14 AS
15 BEGIN
16          if (Select 折扣 from inserted)>0.6
17          begin
18               raiserror('折扣不能大於0.6',16,1)
19                Rollback Transaction --回滾事務。
20          end
21 END
22 GO
23   
24 --在示例二中運用了兩個方法,一個是前面說過的,在Inserted表裏查詢某個字段,還有一個是用Rollback Transaction來回滾操作。如果用下面的SQL語句來進行Insert操作的話,插入記錄將會不成功。
25 INSERT INTO 訂單明細(訂單ID,產品ID,單價,數量,折扣)  
26 VALUES (11077,1,18,1,0.7)  
27 折扣爲0.7, 插入記錄不符合觸發器裏的約束,回滾操作,插入記錄不成功。

after應用範圍:只能使用在表上。


應用示例2:

 

Instead Of觸發器的使用範圍
Instead Of觸發器可以同時在數據表和視圖中使用,通常在以下幾種情況下,建議使用Instead Of觸發器:
* 數據庫裏的數據禁止修改:例如電信部門的通話記錄是不能修改的,一旦修改,則通話費用的計數將不正確。在這個時候,就可以用Instead Of觸發器來跳過Update修改記錄的SQL語句。
* 有可能要回滾修改的SQL語句:如11.5.3節中的例二,用After觸發器並不是一個最好的方法,如果用Instead Of觸發器,在判斷折扣大於0.6時,就中止了更新操作,避免在修改數據之後再回滾操作,減少服務器負擔。
* 在視圖中使用觸發器:因爲After觸發器不能在視圖中使用,如果想在視圖中使用觸發器,就只能用Instead Of觸發器。
* 用自己的方式去修改數據:如不滿意SQL直接的修改數據的方式,可用Instead Of觸發器來控制數據的修改方式和流程。

資料引用:http://book.csdn.net/bookfiles/414/10041414953.shtml

應用技巧:
1、
如何查看舊的記錄?無論何時Insert 或者Update 語句影響一個或者多行時,inserted 臨時表都有記錄行。無論何時Delete 或者Update 語句影響一個或者多行時,deleted 臨時表都有記錄行。對於一個Update 語句,deleted 臨時表有舊行,inserted 臨時表有新行。
2、如何知道觸發器修改了多少條記錄?只要利用@@Rowcount這個系統變量就可以得知更新了多少條記錄
3、如何知道插入記錄的自動編號是多少?用@@IDENTITY可以獲得剛插入記錄的標識值
4、如何知道某個字段是否被修改?if update(列名)...
5、如何返回錯誤信息?Raiserror('除了折扣字段之外的其他字段信息不能修改',16,5)

 

 

以上內容可能有重複的,自己大腦自行過濾~

01 --前面說過的11.5.3節中的例二,用After觸發器並不是一個最好的方法,如果用Instead Of觸發器,在判斷折扣大於0.6時,就中止了更新操作,避免在修改數據之後再回滾操作,減少服務器負擔。現將原來的觸發器改爲Instead Of觸發器:
02   
03 CREATE TRIGGER 訂單明細_Insert
04    ON  訂單明細
05    Instead Of INSERT
06 AS
07 BEGIN
08     SET NOCOUNT ON;
09     declare @訂單ID int, @產品ID int,@單價 money, @數量 smallint,@折扣 real
10     set @訂單ID = (select 訂單ID from inserted)
11     set @產品ID = (select 產品ID from inserted)
12     set @單價 = (select 單價 from inserted)
13     set @數量 = (select 數量 from inserted)
14     set @折扣 = (select 折扣 from inserted)
15        if (@折扣)>0.6
16           raiserror('折扣不能大於0.6',16,1)
17        else
18           INSERT INTO 訂單明細 (訂單ID,產品ID,單價,數量,折扣)
19             VALUES (@訂單ID,@產品ID,@單價,@數量,@折扣)
20 END
21 GO
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章