INSTEAD OF觸發器工作原理
傳遞給為表定義的 INSTEAD OF 觸發器的插入的和刪除的表與傳遞給 AFTER 觸發器的插入的和刪除的表遵守相同的規則。 插入的和刪除的表的格式與在其上定義 INSTEAD OF 觸發器的表的格式相同。 插入的和刪除的表中的每一列都直接映射到基表中的列。
以下是關於引用帶 INSTEAD OF 觸發器的表的 INSERT 或 UPDATE 語句何時必須提供列值的規則,當引用的表不帶 INSTEAD OF 觸發器時也一樣:
-
不能為計算列或具有
timestamp
數據類型的列指定值。 -
不能為具有 IDENTITY 屬性的列指定值,除非該表的 IDENTITY_INSERT 為 ON。 當 IDENTITY_INSERT 為 ON 時,INSERT 語句必須提供一個值。
-
INSERT 語句必須為所有無 DEFAULT 約束的 NOT NULL 列提供值。
-
對於除計算,identity 之外的任何列或
timestamp
列值都是可選的任何允許空值的列或列具有 DEFAULT 定義的 NOT NULL。當 INSERT、UPDATE 或 DELETE 語句引用具有 INSTEAD OF 觸發器的視圖時, 數據庫引擎 將調用該觸發器,而不是對任何表采取任何直接操作。 即使插入的和刪除的表中為該視圖生成的信息格式不同於基表中的數據格式,觸發器也必須使用插入的和刪除的表中的信息來生成實現基表中請求的操作所需的任何語句。
INSTEAD OF觸發器創建
語法:
--聲明數據庫應用。
use 數據庫名;
go
--判斷是否已存在觸發器,如果已存在則刪除。
if exists(select * from sysobjects where name=觸發器名)
drop trigger 觸發器名;
go
--執行創建觸發器
create
--觸發器關鍵字
trigger
--DML 觸發器所屬架構的名稱。 DML 觸發器的作用域是為其創建該觸發器的表或視圖的架構。 不能為 DDL 或登錄觸發器指定
--[dbo.]
--觸發器名稱
[架構名.]{ 表名 | 視圖名}
on
--對其執行 DML 觸發器的表或視圖,有時稱為觸發器表或觸發器視圖。 可以根據需要指定表或視圖的完全限定名稱。 視圖只能被 INSTEAD OF 觸發器引用。 不能對局部或全局臨時表定義 DML 觸發器。
[架構名.]觸發器名
with
--對CREATE TRIGGER 語句的文本進行模糊處理。使用WITH ENCRYPTION可以防止將觸發器作為SQL Server復制的一部分進行發布。不能為 CLR 觸發器指定 WITH ENCRYPTION。(指定此選項將為觸發器加密)
[encryption][,]
--指示觸發器已本機編譯。 (只能應用於table)
--內存優化表上的觸發器需要使用此選項。
--[native_compilation][,]
--確保不能刪除或更改觸發器引用的表。(只能應用於table)
--內存優化表上的觸發器需要使用此選項,但此選項不支持傳統表上的觸發器。
[schemabinding][,]
--EXECUTE AS (后面可以跟函數,存儲過程等)
--指定用於執行該觸發器的安全上下文。 允許您控制 SQL Server 實例用於驗證被觸發器引用的任意數據庫對象的權限的用戶帳戶。
--內存優化表上的觸發器需要使用此選項。
--[execute as clause]
--指定執行 DML 觸發器而不是觸發 SQL 語句,因此,其優先級高於觸發語句的操作。 不能為 DDL 或登錄觸發器指定 INSTEAD OF。
--對於表或視圖,每個 INSERT、UPDATE 或 DELETE 語句最多可定義一個 INSTEAD OF 觸發器。 但是,可以為具有自己的 INSTEAD OF 觸發器的多個視圖定義視圖。
--INSTEAD OF 觸發器不可以用於使用 WITH CHECK OPTION 的可更新視圖。 如果將 INSTEAD OF 觸發器添加到指定了 WITH CHECK OPTION 的可更新視圖中,則 SQL Server 將引發錯誤。 用戶須用 ALTER VIEW 刪除該選項后才能定義 INSTEAD OF 觸發器。
instead of
--指定數據修改語句,這些語句可在 DML 觸發器對此表或視圖進行嘗試時激活該觸發器。 必須至少指定一個選項。 在觸發器定義中允許使用上述選項的任意順序組合。
--對於 INSTEAD OF 觸發器,不允許對具有指定級聯操作 ON DELETE 的引用關系的表使用 DELETE 選項。 同樣,也不允許對具有指定級聯操作 ON UPDATE 的引用關系的表使用 UPDATE 選項。
{ [insert] [,] [update] [,] [delete] }
--指定應該再添加一個現有類型的觸發器。 WITH APPEND 不能與 INSTEAD OF 觸發器一起使用。如果顯式聲明了 AFTER 觸發器,則也不能使用該子句。
--僅當為了向后兼容而指定了 FOR 時(但沒有 INSTEAD OF 或 AFTER)時,才能使用 WITH APPEND。 如果指定了 EXTERNAL NAME(即觸發器為 CLR 觸發器),則不能指定 WITH APPEND。
--with append
--指示當復制代理修改涉及到觸發器的表時,不應執行觸發器。
--not for replication
as
begin
sql_statement
end
go
示例:
--聲明數據庫應用。
use testss;
go
--判斷是否已存在觸發器,如果已存在則刪除。
if exists(select * from sysobjects where name='insteadoftri')
drop trigger insteadoftri;
go
--執行創建觸發器
create
--觸發器關鍵字
trigger
--DML 觸發器所屬架構的名稱。 DML 觸發器的作用域是為其創建該觸發器的表或視圖的架構。 不能為 DDL 或登錄觸發器指定
--[dbo.]
--觸發器名稱
dbo.insteadoftri
on
--對其執行 DML 觸發器的表或視圖,有時稱為觸發器表或觸發器視圖。 可以根據需要指定表或視圖的完全限定名稱。 視圖只能被 INSTEAD OF 觸發器引用。 不能對局部或全局臨時表定義 DML 觸發器。
dbo.test1
with
--對CREATE TRIGGER 語句的文本進行模糊處理。使用WITH ENCRYPTION可以防止將觸發器作為SQL Server復制的一部分進行發布。不能為 CLR 觸發器指定 WITH ENCRYPTION。(指定此選項將為觸發器加密)
encryption,
--指示觸發器已本機編譯。 (只能應用於table)
--內存優化表上的觸發器需要使用此選項。
--[native_compilation][,]
--確保不能刪除或更改觸發器引用的表。(只能應用於table)
--內存優化表上的觸發器需要使用此選項,但此選項不支持傳統表上的觸發器。
schemabinding
--EXECUTE AS (后面可以跟函數,存儲過程等)
--指定用於執行該觸發器的安全上下文。 允許您控制 SQL Server 實例用於驗證被觸發器引用的任意數據庫對象的權限的用戶帳戶。
--內存優化表上的觸發器需要使用此選項。
--[execute as clause]
--指定執行 DML 觸發器而不是觸發 SQL 語句,因此,其優先級高於觸發語句的操作。 不能為 DDL 或登錄觸發器指定 INSTEAD OF。
--對於表或視圖,每個 INSERT、UPDATE 或 DELETE 語句最多可定義一個 INSTEAD OF 觸發器。 但是,可以為具有自己的 INSTEAD OF 觸發器的多個視圖定義視圖。
--INSTEAD OF 觸發器不可以用於使用 WITH CHECK OPTION 的可更新視圖。 如果將 INSTEAD OF 觸發器添加到指定了 WITH CHECK OPTION 的可更新視圖中,則 SQL Server 將引發錯誤。 用戶須用 ALTER VIEW 刪除該選項后才能定義 INSTEAD OF 觸發器。
instead of
--指定數據修改語句,這些語句可在 DML 觸發器對此表或視圖進行嘗試時激活該觸發器。 必須至少指定一個選項。 在觸發器定義中允許使用上述選項的任意順序組合。
--對於 INSTEAD OF 觸發器,不允許對具有指定級聯操作 ON DELETE 的引用關系的表使用 DELETE 選項。 同樣,也不允許對具有指定級聯操作 ON UPDATE 的引用關系的表使用 UPDATE 選項。
insert,update,delete
--指定應該再添加一個現有類型的觸發器。 WITH APPEND 不能與 INSTEAD OF 觸發器一起使用。如果顯式聲明了 AFTER 觸發器,則也不能使用該子句。
--僅當為了向后兼容而指定了 FOR 時(但沒有 INSTEAD OF 或 AFTER)時,才能使用 WITH APPEND。 如果指定了 EXTERNAL NAME(即觸發器為 CLR 觸發器),則不能指定 WITH APPEND。
--with append
--指示當復制代理修改涉及到觸發器的表時,不應執行觸發器。
not for replication
as
begin
if (select count(1) from inserted) = 1 and (select count(1) from deleted) = 0
begin
print('insert');
insert into dbo.test1(name,sex,age,classid,height,xml1,xml2)
select top 1 name,sex,age,classid,height,xml1,xml2 from inserted order by id desc;
end
else if (select count(1) from deleted) = 1 and (select count(1) from inserted) = 0
begin
print('delete');
delete from dbo.test1 where id=(select top 1 id from deleted order by id desc);
end
else
begin
print('update');
update dbo.test1 set name=inserted.name,sex=inserted.sex,age=inserted.age,classid=inserted.classid,height=inserted.height,
xml1=inserted.xml1,xml2=inserted.xml2
from inserted
where dbo.test1.id=(select top 1 id from deleted order by id desc);
end
end
go
示例結果:
INSTEAD OF觸發器優缺點
優點:
1、可以實現在對數據操作之前更嚴格的檢查和校驗。
2、可定義在表上,也可以定義在視圖上,同一操作只能定義一個。
3、指定執行 DML 觸發器而不是觸發 SQL 語句,因此,其優先級高於觸發語句的操作。
缺點:
1、可移植性差。
2、占用服務器資源,給服務器造成壓力。
3、執行速度主要取決於數據庫服務器的性能與觸發器代碼的復雜程度。
4、觸發器會使編程時源碼的結構被迫打亂,為將程序修改、源碼閱讀帶來困難。