修改觸發器規則
修改CREATE TRIGGER語句以前創建的 DML、DDL 或登錄觸發器的定義。觸發器是通過使用CREATE TRIGGER創建的。這些觸發器可以由Transact-SQL語句直接創建,也可以由程序集方法創建,這些方法在Microsoft .NET Framework公共語言運行時 (CLR)中創建並上傳到SQL Server的實例。
DML 觸發器
通過表和視圖上的INSTEAD OF觸發器,ALTER TRIGGER支持可手動更新的視圖。SQL Server以相同的方式對所有類型的觸發器(AFTER、INSTEAD-OF)應用ALTER TRIGGER。
可以使用sp_settriggerorder來指定要對表執行的第一個和最后一個AFTER觸發器。 對一個表只能指定第一個和最后一個AFTER觸發器。 如果在同一個表上還有其他AFTER觸發器,這些觸發器將隨機執行。
如果ALTER TRIGGER語句更改了第一個或最后一個觸發器,將刪除所修改觸發器上設置的第一個或最后一個屬性,並且必須使用sp_settriggerorder重置順序值。
只有在成功執行觸發SQL語句之后,才會執行AFTER觸發器。 判斷執行成功的標准是:執行了所有與已更新對象或已刪除對象相關聯的引用級聯操作和約束檢查。 AFTER 觸發器操作要檢查觸發語句的效果,也包括所有由觸發語句引起的 UPDATE 和 DELETE 引用級聯操作。
如果一個子表或引用表上的 DELETE 操作是由於父表的 CASCADE DELETE 操作所引起的,並且子表上定義了 DELETE 的 INSTEAD OF 觸發器,那么將忽略該觸發器並執行 DELETE 操作。
DDL 觸發器
與DML觸發器不同,DDL觸發器的作用域不是架構。 因此,在查詢有關DDL觸發器的元數據時,不能使用OBJECT_ID、OBJECT_NAME、OBJECTPROPERTY 和 OBJECTPROPERTY(EX)。 請改用目錄視圖。 有關詳細信息,請參閱獲取有關 DDL 觸發器的信息。
登錄觸發器
Azure SQL Database 不支持針對登錄事件的觸發器。
Permissions
若要更改DML觸發器,需要對於定義該觸發器所在的表或視圖擁有 ALTER 權限。
若要更改定義了服務器范圍 (ON ALL SERVER) 的DDL觸發器或者更改登錄觸發器,需要對該服務器擁有CONTROL SERVER權限。 若要更改定義了數據庫范圍 (ON DATABASE) 的DDL觸發器,需要對當前數據庫擁有ALTER ANY DATABASE DDL TRIGGER權限。
觸發器修改
語法:
--聲明數據庫引用
use 數據庫;
go
--修改觸發器
alter
--觸發器標識符
trigger
--DML觸發器所屬架構的名稱。 DML觸發器的作用域是為其創建該觸發器的表或視圖的架構。不能為DDL或登錄觸發器指定
--[dbo][.]觸發器名稱
[架構名稱].[觸發器名]
on
--對其執行DML觸發器的表或視圖,有時稱為觸發器表或觸發器視圖。可以根據需要指定表或視圖的完全限定名稱。視圖只能被INSTEAD OF觸發器引用。不能對局部或全局臨時表定義DML觸發器。
--DATABASE
--將 DDL 觸發器的作用域應用於當前數據庫。 如果指定了此參數,則只要當前數據庫中出現 event_type 或 event_group,就會激發該觸發器。
--ALL SERVER
--適用范圍: SQL Server 2008 到 SQL Server 2017。
--將 DDL 或登錄觸發器的作用域應用於當前服務器。 如果指定了此參數,則只要當前服務器中的任何位置出現 event_type 或 event_group,就會激發該觸發器。
{ [架構名].表名| [架構名].視圖 } { database| all server } { all server }
--with
--此屬性適用於所有觸發器類型
--加密包含ALTER TRIGGER語句文本的sys.syscomments和sys.sql_modules項。使用WITH ENCRYPTION可以防止將觸發器作為SQL Server復制的一部分進行發布。不能為CLR觸發器指定WITH ENCRYPTION。
--encryption,
--指示觸發器已本機編譯。(只能應用於DML觸發器的table)
--內存優化表上的觸發器需要使用此選項。
--native_compilation,
--確保不能刪除或更改觸發器引用的表。(只能應用於DML觸發器的table)
--內存優化表上的觸發器需要使用此選項,但此選項不支持傳統表上的觸發器。
--schemabinding
--此屬性適用於所有觸發器類型
--{ EXEC | EXECUTE } AS { SELF | OWNER | 'user_name' }
--CALLER
--指定模塊內的語句在模塊調用方的上下文中執行。 執行模塊的用戶不僅必須對模塊本身擁有適當的權限,還要對模塊引用的任何數據庫對象擁有適當權限。
--CALLER 是除隊列外的所有模塊的默認值,與 SQL Server 2005 行為相同。
--CALLER 不能在 CREATE QUEUE 或 ALTER QUEUE 語句中指定。
--SELF
--EXECUTE AS SELF 與 EXECUTE AS user_name 等價,其中指定用戶是創建或更改模塊的用戶。 創建或更改模塊的用戶的實際用戶 ID 存儲在 sys.sql_modules 或 sys.service_queues 目錄視圖的 execute_as_principal_id 列中。
--SELF 是隊列的默認值。
--OWNER
--指定模塊內的語句在模塊的當前所有者上下文中執行。 如果模塊沒有指定的所有者,則使用模塊架構的所有者。 不能為 DDL 或登錄觸發器指定 OWNER。
--' user_name '
--指定模塊內的語句在 user_name 指定的用戶的上下文中執行。 將根據 user_name 來驗證對模塊內任意對象的權限。 不能為具有服務器作用域的 DDL 觸發器或登錄觸發器指定 user_name。 請改用 login_name。
--user_name 必須存在於當前數據庫中,並且必須是單一實例帳戶。 user_name 不能為組、角色、證書、密鑰或內置帳戶,如 NT AUTHORITY\LocalService、NT AUTHORITY\NetworkService 或 NT AUTHORITY\LocalSystem。
--執行上下文的用戶 ID 存儲在元數據中,可以在 sys.sql_modules 或 sys.assembly_modules 目錄視圖的 execute_as_principal_id 列查看。
--內存優化表上的觸發器需要使用此選項。
--execute as { caller | self | owner | 'username'}
--FOR | AFTER
--AFTER 指定 DML 觸發器僅在觸發 SQL 語句中指定的所有操作都已成功執行時才被觸發。 所有的引用級聯操作和約束檢查也必須在激發此觸發器之前成功完成。
--如果僅指定 FOR 關鍵字,則 AFTER 為默認值。
--不能對視圖定義 AFTER 觸發器。
--INSTEAD OF
--指定執行 DML 觸發器而不是觸發 SQL 語句,因此,其優先級高於觸發語句的操作。 不能為 DDL 或登錄觸發器指定 INSTEAD OF。
--對於表或視圖,每個 INSERT、UPDATE 或 DELETE 語句最多可定義一個 INSTEAD OF 觸發器。 但是,可以為具有自己的 INSTEAD OF 觸發器的多個視圖定義視圖。
--不允許在使用 WITH CHECK OPTION 創建的視圖上定義 INSTEAD OF 觸發器。 將 INSTEAD OF 觸發器添加到為其指定了 WITH CHECK OPTION 的視圖時, SQL Server 將引發錯誤。 用戶必須用 ALTER VIEW 刪除該選項后才能定義 INSTEAD OF 觸發器。
{ for | after | instead of }
--{ [DELETE] [,] [INSERT] [,] [UPDATE] }
--指定數據修改語句,這些語句可在 DML 觸發器對此表或視圖進行嘗試時激活該觸發器。 必須至少指定一個選項。 在觸發器定義中允許使用上述選項的任意順序組合。
--對於 INSTEAD OF 觸發器,不允許對具有指定級聯操作 ON DELETE 的引用關系的表使用 DELETE 選項。 同樣,也不允許對具有指定級聯操作 ON UPDATE 的引用關系的表使用 UPDATE 選項。
--event_type
--執行之后將導致激發 DDL 觸發器的 Transact-SQL 語言事件的名稱。 DDL 事件中列出了 DDL 觸發器的有效事件。
--event_group
--預定義的 Transact-SQL 語言事件分組的名稱。 執行任何屬於 event_group 的 Transact-SQL 語言事件之后,都將激發 DDL 觸發器。 DDL 事件組中列出了 DDL 觸發器的有效事件組。 ALTER TRIGGER 運行完成后,event_group 還將充當宏,將它涉及的事件類型添加到 sys.trigger_events 目錄視圖中。
{ [insert] [,] [update] [,] [delete] } { event_type [ ,...n ] | event_group }
--此屬性應用於DML觸發器的表和視圖
--指示當復制代理修改涉及到觸發器的表時,不應執行觸發器。
--not for replication
as
begin
sql_statement;
end;
示例:本示例演示修改DML插入觸發器。
--聲明數據庫引用
use testss;
go
--修改觸發器
alter
--觸發器標識符
trigger
--DML觸發器所屬架構的名稱。 DML觸發器的作用域是為其創建該觸發器的表或視圖的架構。不能為DDL或登錄觸發器指定
--[dbo][.]觸發器名稱
dbo.inserttri
on
--對其執行DML觸發器的表或視圖,有時稱為觸發器表或觸發器視圖。可以根據需要指定表或視圖的完全限定名稱。視圖只能被INSTEAD OF觸發器引用。不能對局部或全局臨時表定義DML觸發器。
dbo.test1
with
--此屬性適用於所有觸發器類型
--加密包含ALTER TRIGGER語句文本的sys.syscomments和sys.sql_modules項。使用WITH ENCRYPTION可以防止將觸發器作為SQL Server復制的一部分進行發布。不能為CLR觸發器指定WITH ENCRYPTION。
--encryption,
--指示觸發器已本機編譯。(只能應用於DML觸發器的table)
--內存優化表上的觸發器需要使用此選項。
--native_compilation,
--確保不能刪除或更改觸發器引用的表。(只能應用於DML觸發器的table)
--內存優化表上的觸發器需要使用此選項,但此選項不支持傳統表上的觸發器。
--schemabinding
--此屬性適用於所有觸發器類型
--{ EXEC | EXECUTE } AS { SELF | OWNER | 'user_name' }
--CALLER
--指定模塊內的語句在模塊調用方的上下文中執行。 執行模塊的用戶不僅必須對模塊本身擁有適當的權限,還要對模塊引用的任何數據庫對象擁有適當權限。
--CALLER 是除隊列外的所有模塊的默認值,與 SQL Server 2005 行為相同。
--CALLER 不能在 CREATE QUEUE 或 ALTER QUEUE 語句中指定。
--SELF
--EXECUTE AS SELF 與 EXECUTE AS user_name 等價,其中指定用戶是創建或更改模塊的用戶。 創建或更改模塊的用戶的實際用戶 ID 存儲在 sys.sql_modules 或 sys.service_queues 目錄視圖的 execute_as_principal_id 列中。
--SELF 是隊列的默認值。
--OWNER
--指定模塊內的語句在模塊的當前所有者上下文中執行。 如果模塊沒有指定的所有者,則使用模塊架構的所有者。 不能為 DDL 或登錄觸發器指定 OWNER。
--' user_name '
--指定模塊內的語句在 user_name 指定的用戶的上下文中執行。 將根據 user_name 來驗證對模塊內任意對象的權限。 不能為具有服務器作用域的 DDL 觸發器或登錄觸發器指定 user_name。 請改用 login_name。
--user_name 必須存在於當前數據庫中,並且必須是單一實例帳戶。 user_name 不能為組、角色、證書、密鑰或內置帳戶,如 NT AUTHORITY\LocalService、NT AUTHORITY\NetworkService 或 NT AUTHORITY\LocalSystem。
--執行上下文的用戶 ID 存儲在元數據中,可以在 sys.sql_modules 或 sys.assembly_modules 目錄視圖的 execute_as_principal_id 列查看。
--內存優化表上的觸發器需要使用此選項。
execute as self
--FOR | AFTER
--AFTER 指定 DML 觸發器僅在觸發 SQL 語句中指定的所有操作都已成功執行時才被觸發。 所有的引用級聯操作和約束檢查也必須在激發此觸發器之前成功完成。
--如果僅指定 FOR 關鍵字,則 AFTER 為默認值。
--不能對視圖定義 AFTER 觸發器。
for
--{ [DELETE] [,] [INSERT] [,] [UPDATE] }
--指定數據修改語句,這些語句可在 DML 觸發器對此表或視圖進行嘗試時激活該觸發器。 必須至少指定一個選項。 在觸發器定義中允許使用上述選項的任意順序組合。
--對於 INSTEAD OF 觸發器,不允許對具有指定級聯操作 ON DELETE 的引用關系的表使用 DELETE 選項。 同樣,也不允許對具有指定級聯操作 ON UPDATE 的引用關系的表使用 UPDATE 選項。
insert
--此屬性應用於DML觸發器的表和視圖
--指示當復制代理修改涉及到觸發器的表時,不應執行觸發器。
not for replication
as
begin
declare @sname nvarchar(100)=NULL,@sclassid int=NULL;
set @sname=(select name from inserted);
set @sclassid=(select classid from inserted);
--判斷是否需要向test插入name
if @sname is not null
begin
if(select id from dbo.test2 where name=@sname) is null
begin
insert into dbo.test2(name) values(@sname);
end;
end;
--判斷是否需要向test3插入classid
if @sclassid is not null
begin
if (select id from dbo.test3 where id=@sclassid) is not null
begin
print(@sclassid);
--insert into dbo.test1(name,sex,age,classid,height,xml1,xml2)
--select name,sex,age,classid,height,xml1,xml2 from inserted;
end;
end;
end;
示例結果:當向test1表中插入classid時,插入test3已存在的id時會打印1,插入test3不存在的id時不會打印1。