觸發(fā)器分類
SQL Server提供三類觸發(fā)器:
- DML觸發(fā)器:在數(shù)據(jù)庫中發(fā)生數(shù)據(jù)操作(Insert、Update 或Delete)事件時自動執(zhí)行。
- DDL觸發(fā)器:在服務(wù)器或數(shù)據(jù)庫中發(fā)生數(shù)據(jù)定義(如Create、Alter、Drop)事件時自動執(zhí)行。
- 登錄觸發(fā)器:在與SQL Server實例建立用戶會話時自動執(zhí)行,主要用來審核和控制服務(wù)器會話。
與Oracle對比,SQL Server的觸發(fā)器有以下特點:
- SQL Server不支持Oracle的Before觸發(fā)器功能。
雖然沒有Before觸發(fā)器功能,但是SQL Server可以利用Instead Of重寫關(guān)鍵字,然后在觸發(fā)器中加入想要在DML操作之前的事務(wù)。
- SQL Server不支持Oracle的row-level觸發(fā)器功能,而只支持類似Oracle的statement-level形式的觸發(fā)器,即DML語句只會激活一次觸發(fā)器的執(zhí)行,而不管其影響了多少條記錄。
Oracle的row-level觸發(fā)器:創(chuàng)建觸發(fā)器時附加for each row關(guān)鍵字,對觸發(fā)事件所影響的每條記錄都執(zhí)行一次觸發(fā)器。如果一個update語句修改了10條記錄,則row-level觸發(fā)器會執(zhí)行10次。
??雖然SQL Server不支持row-level,但是我們可以通過INSERTED表和DELETED表的功能。比如Oracle觸發(fā)器中的這條語句:
for each row when(abs(new.sal>old.sal)>2000)
在SQL Server中可以寫成這樣:
if(select max(abs(i.sal-d.sal)) from inserted i,deleted d
where i.empno=d.empno)>2000
- SQL Server的DDL觸發(fā)器只支持After形式。
SQL Server的DDL觸發(fā)器只有在完成相應(yīng)的DDL語句之后才會被觸發(fā),因此DDL觸發(fā)器不能使用INSTEAD OF選項。
- SQL Server的DDL觸發(fā)器除與Oracle的DDL觸發(fā)器功能類似外,還包含了Oracle的系統(tǒng)觸發(fā)器的部分功能
DML觸發(fā)器
了解DML觸發(fā)器
當(dāng)數(shù)據(jù)庫中發(fā)生數(shù)據(jù)操作語言 (DML) 事件時將調(diào)用 DML 觸發(fā)器。DML 事件包括在指定表或視圖中修改數(shù)據(jù)的 INSERT 語句、UPDATE 語句或 DELETE 語句。DML 觸發(fā)器可以查詢其他表,還可以包含復(fù)雜的 Transact-SQL 語句。將觸發(fā)器和觸發(fā)它的語句作為可在觸發(fā)器內(nèi)回滾的單個事務(wù)對待。如果檢測到錯誤(例如,磁盤空間不足),則整個事務(wù)即自動回滾。
??DML 觸發(fā)器在以下方面非常有用:
- DML 觸發(fā)器可通過數(shù)據(jù)庫中的相關(guān)表實現(xiàn)級聯(lián)更改。不過,通過級聯(lián)引用完整性約束可以更有效地進(jìn)行這些更改。
- DML 觸發(fā)器可以防止惡意或錯誤的 INSERT、UPDATE 以及 DELETE 操作,并強制執(zhí)行比 CHECK 約束定義的限制更為復(fù)雜的其他限制。
與 CHECK 約束不同,DML 觸發(fā)器可以引用其他表中的列。例如,觸發(fā)器可以使用另一個表中的 SELECT 比較插入或更新的數(shù)據(jù),以及執(zhí)行其他操作,如修改數(shù)據(jù)或顯示用戶定義錯誤信息。
DML 觸發(fā)器可以評估數(shù)據(jù)修改前后表的狀態(tài),并根據(jù)該差異采取措施。 - 一個表中的多個同類 DML 觸發(fā)器(INSERT、UPDATE 或 DELETE)允許采取多個不同的操作來響應(yīng)同一個修改語句。
DML 觸發(fā)器的類型
(1)AFTER 觸發(fā)器
??在執(zhí)行了 INSERT、UPDATE 或 DELETE 語句操作之后執(zhí)行 AFTER 觸發(fā)器。指定 AFTER 與指定 FOR 相同,它是 Microsoft SQL Server 早期版本中唯一可用的選項。AFTER 觸發(fā)器只能在表上指定。
??AFTER觸發(fā)器僅適用于表,每個觸發(fā)操作(UPDATE、DELETE 和 INSERT)可以包含多個觸發(fā)器。
??由上圖可見AFTER觸發(fā)器執(zhí)行晚于約束處理、聲明性引用操作、創(chuàng)建插入的和刪除的表。
(2)INSTEAD OF 觸發(fā)器
??執(zhí)行 INSTEAD OF 觸發(fā)器代替通常的觸發(fā)動作。還可為帶有一個或多個基表的視圖定義 INSTEAD OF 觸發(fā)器,而這些觸發(fā)器能夠擴(kuò)展視圖可支持的更新類型。
??INSTEAD OF觸發(fā)器既可以用于表也可以用于視圖,但是每個觸發(fā)操作(UPDATE、DELETE 和 INSERT)只能包含一個觸發(fā)器。
??由上圖可見INSTEAD OF觸發(fā)器早于約束處理,替代觸發(fā)操作,晚于創(chuàng)建插入的和刪除的表。
(3)CLR 觸發(fā)器
??CLR 觸發(fā)器可以是 AFTER 觸發(fā)器或 INSTEAD OF 觸發(fā)器。CLR 觸發(fā)器還可以是 DDL 觸發(fā)器。CLR 觸發(fā)器將執(zhí)行在托管代碼(在 .NET Framework 中創(chuàng)建并在 SQL Server 中上載的程序集的成員)中編寫的方法,而不用執(zhí)行 Transact-SQL 存儲過程。
創(chuàng)建DML觸發(fā)器
當(dāng)DML觸發(fā)器執(zhí)行的時候,會產(chǎn)生兩個只讀的臨時表:inserted表和deleted表。這兩個表的結(jié)構(gòu)和觸發(fā)器所在的表的結(jié)構(gòu)相同。當(dāng)觸發(fā)器執(zhí)行完成之后,這兩個表就會被自動刪除。
??當(dāng)對觸發(fā)器表執(zhí)行INSERT操作時,新插入的行將同時被添加到inserted表中,inserted表中的行是觸發(fā)器表中新添加行的副本。
??當(dāng)對觸發(fā)器表執(zhí)行DELETE操作時,行將從觸發(fā)器表中刪除,同時被存入deleted表中。deleted表和觸發(fā)器表沒有相同的行。
??當(dāng)對觸發(fā)器表執(zhí)行UPDATE操作時,先從觸發(fā)器表中刪除舊行,然后再插入新行。其中被刪除的舊行被插入到deleted表中,插入的新行的副本被插入到inserted表中。
??創(chuàng)建DML觸發(fā)器語法如下:
IF EXISTS(select * from sys.sysobjects where name='<觸發(fā)器名>')
DROP TIGGER <觸發(fā)器名>
GO
CREATE TIGGER <觸發(fā)器名>
ON <表名|視圖名>
[WITH ENCRYPTION]
FOR|AFTER|INSTEAD OF
[INSERT][,][UPDATE][,][DELETE]
AS
<T-SQL語句或語句塊>
- WITH ENCRYPTION:對觸發(fā)器進(jìn)行加密處理
- FOR|AFTER:FOR和AFTER意義相同,指定觸發(fā)器中在相應(yīng)的DML操作成功執(zhí)行后才觸發(fā)。
- INSTEAD OF:指定執(zhí)行DML觸發(fā)器用于“代替”引發(fā)觸發(fā)器執(zhí)行的DML語句。
- [INSERT][,][UPDATE][,][DELETE]:指定能夠激活觸發(fā)器的操作,必須至少指定一個操作
使用觸發(fā)器小Tips
①觸發(fā)器本身就是一個事務(wù),所以在觸發(fā)器里面可以對修改數(shù)據(jù)進(jìn)行一些特殊的檢查。如果不滿足可以利用事務(wù)回滾,撤銷操作(區(qū)別于過程和函數(shù),過程和函數(shù)不能在語句塊里面進(jìn)行事務(wù)的commit、rollback等操作)。
②SQL Server不支持Oracle創(chuàng)建觸發(fā)器時的update of column的語法形式,也就是不能判斷指定哪一列被Update操作才觸發(fā)觸發(fā)器。但是在SQL Server中我們可以通過update(column_name)的形式來判斷列是否被修改過,詳見示例(2)。
【示例】
(1)級聯(lián)修改數(shù)據(jù)
--update更新類型觸發(fā)器
if (object_id('tgr_classes_update', 'TR') is not null)
drop trigger tgr_classes_update
go
create trigger tgr_classes_update
on classes
for update
as
declare @oldName varchar(20), @newName varchar(20);
--更新前的數(shù)據(jù)
select @oldName = name from deleted;
if (exists (select * from student where name like '%'+ @oldName + '%'))
begin
--更新后的數(shù)據(jù)
select @newName = name from inserted;
update student set name = replace(name, @oldName, @newName)
where name like '%'+ @oldName + '%';
print '級聯(lián)修改數(shù)據(jù)成功!';
end
else
print '無需修改student表!';
go
(2)審計對emp表的sal列的update操作
create tigger tri_emp_sal_audit
on emp
after update
as
if update(sal)
insert into emp_sal_audit
select i.empno,d.sal,i.sal,user,getdate()
from inserted i,deleted d
where i.empno=d.empno
go
設(shè)計INSTEAD OF觸發(fā)器
INSTEAD OF 觸發(fā)器的主要優(yōu)點是可以使不能更新的視圖支持更新。基于多個基表的視圖必須使用 INSTEAD OF 觸發(fā)器來支持引用多個表中數(shù)據(jù)的插入、更新和刪除操作。INSTEAD OF 觸發(fā)器的另一個優(yōu)點是使您得以編寫這樣的邏輯代碼:在允許批處理的其他部分成功的同時拒絕批處理中的某些部分。
??INSTEAD OF 觸發(fā)器可以進(jìn)行以下操作:
- 忽略批處理中的某些部分。
- 不處理批處理中的某些部分并記錄有問題的行。
- 如果遇到錯誤情況則采取備用操作。
適用INSTEAD OF觸發(fā)器注意事項:
- 對于含有使用 DELETE 或 UPDATE 級聯(lián)操作定義的外鍵的表,不能定義 INSTEAD OF DELETE 和 INSTEAD OF UPDATE 觸發(fā)器。
- 因為INSTEAD OF觸發(fā)器的內(nèi)容會代替DELETE、UPDATE、INSERT觸發(fā)操作,所以在INSTEAD OF觸發(fā)器內(nèi)要通過inserted表和deleted表重寫DML操作。
【示例】
(1)創(chuàng)建觸發(fā)器禁止用戶在每天晚上18:00:00到23:59:59之間以及凌晨00:00:00到06:59:59之間對emp表執(zhí)行update操作。
create tigger tri_deny_emp_update
on emp
instead of update
as
if(datepart(hour,getdate())>=18 and datepart(hour,getdate())<=23)
or(datepart(hour,getdate())>=0 and datepart(hour,getdate())<=6)
print 'Update not allowed now.'
else
begin
delete from emp where empno in (select empno from deleted)
insert into emp select * from inserted
end
go
(2)在下列 Transact-SQL 語句序列中,INSTEAD OF 觸發(fā)器更新視圖中的兩個基表。另外,顯示以下處理錯誤的方法:
- 忽略對 Person 表的重復(fù)插入,并且插入的信息將記錄在 PersonDuplicates 表中。
- 將對 EmployeeTable 的重復(fù)插入轉(zhuǎn)變?yōu)?UPDATE 語句,該語句將當(dāng)前信息檢索至 EmployeeTable,而不會產(chǎn)生重復(fù)鍵沖突。
T-SQL 語句創(chuàng)建兩個基表、一個視圖、一個記錄錯誤表和視圖上的 INSTEAD OF 觸發(fā)器。以下表將個人數(shù)據(jù)和業(yè)務(wù)數(shù)據(jù)分開并且是視圖的基表。
-- 兩個基表
CREATE TABLE Person
(
SSN char(11) PRIMARY KEY,
Name nvarchar(100),
Address nvarchar(100),
Birthdate datetime
)
CREATE TABLE EmployeeTable
(
EmployeeID int PRIMARY KEY,
SSN char(11) UNIQUE,
Department nvarchar(10),
Salary money,
CONSTRAINT FKEmpPer FOREIGN KEY (SSN)
REFERENCES Person (SSN)
)
-- 可記錄對插入具有重復(fù)的社會保障號的行的嘗試。
-- PersonDuplicates 表記錄插入的值、嘗試插入的用戶的姓名和插入的時間。
CREATE TABLE PersonDuplicates
(
SSN char(11),
Name nvarchar(100),
Address nvarchar(100),
Birthdate datetime,
InsertSNAME nchar(100),
WhenInserted datetime
)
-- 一個視圖
CREATE VIEW Employee AS
SELECT P.SSN as SSN, Name, Address,
Birthdate, EmployeeID, Department, Salary
FROM Person P, EmployeeTable E
WHERE P.SSN = E.SSN
INSTEAD OF觸發(fā)器:
CREATE TRIGGER IO_Trig_INS_Employee ON Employee
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON
-- Check for duplicate Person. If there is no duplicate, do an insert.
IF (NOT EXISTS (SELECT P.SSN
FROM Person P, inserted I
WHERE P.SSN = I.SSN))
INSERT INTO Person
SELECT SSN,Name,Address,Birthdate FROM inserted
ELSE
-- Log an attempt to insert duplicate Person row in PersonDuplicates table.
INSERT INTO PersonDuplicates
SELECT SSN,Name,Address,Birthdate,SUSER_SNAME(),GETDATE() FROM inserted
-- Check for duplicate Employee. If no there is duplicate, do an INSERT.
IF (NOT EXISTS (SELECT E.SSN
FROM EmployeeTable E, inserted
WHERE E.SSN = inserted.SSN))
INSERT INTO EmployeeTable
SELECT EmployeeID,SSN, Department, Salary FROM inserted
ELSE
--If there is a duplicate, change to UPDATE so that there will not
--be a duplicate key violation error.
UPDATE EmployeeTable
SET EmployeeID = I.EmployeeID,
Department = I.Department,
Salary = I.Salary
FROM EmployeeTable E, inserted I WHERE E.SSN = I.SSN
END
DDL觸發(fā)器
了解DDL觸發(fā)器
像常規(guī)觸發(fā)器一樣,DDL 觸發(fā)器將激發(fā)存儲過程以響應(yīng)事件。但與 DML 觸發(fā)器不同的是,它們不會為響應(yīng)針對表或視圖的 UPDATE、INSERT 或 DELETE 語句而激發(fā)。相反,它們將為了響應(yīng)各種數(shù)據(jù)定義語言 (DDL) 事件而激發(fā)。這些事件主要與以關(guān)鍵字 CREATE、ALTER 和 DROP 開頭的 Transact-SQL 語句對應(yīng)。執(zhí)行 DDL 式操作的系統(tǒng)存儲過程也可以激發(fā) DDL 觸發(fā)器。
測試您的 DDL 觸發(fā)器以確定它們是否響應(yīng)運行的系統(tǒng)存儲過程。例如,CREATE TYPE 語句和 sp_addtype 存儲過程都將激發(fā)針對 CREATE_TYPE 事件創(chuàng)建的 DDL 觸發(fā)器。
DDL 觸發(fā)器可用于管理任務(wù),例如審核和控制數(shù)據(jù)庫操作。如果要執(zhí)行以下操作,請使用 DDL 觸發(fā)器:
- 要防止對數(shù)據(jù)庫架構(gòu)進(jìn)行某些更改。
- 希望數(shù)據(jù)庫中發(fā)生某種情況以響應(yīng)數(shù)據(jù)庫架構(gòu)中的更改。
- 要記錄數(shù)據(jù)庫架構(gòu)中的更改或事件。
DDL觸發(fā)器的作用域
在響應(yīng)當(dāng)前數(shù)據(jù)庫或服務(wù)器上處理的 Transact-SQL 事件時,可以觸發(fā) DDL 觸發(fā)器。觸發(fā)器的作用域取決于事件。例如,每當(dāng)數(shù)據(jù)庫中或服務(wù)器實例上發(fā)生 CREATE_TABLE 事件時,都會激發(fā)為響應(yīng) CREATE_TABLE 事件創(chuàng)建的 DDL 觸發(fā)器。僅當(dāng)服務(wù)器上發(fā)生 CREATE_LOGIN 事件時,才能激發(fā)為響應(yīng)CREATE_LOGIN 事件創(chuàng)建的 DDL 觸發(fā)器。
DDL事件以及DDL事件組
請參閱:https://msdn.microsoft.com/zh-cn/library/bb522542(v=sql.105).aspx
使用 EVENTDATA 函數(shù)
使用 EVENTDATA 函數(shù),可以捕獲有關(guān)激發(fā) DDL 觸發(fā)器的事件的信息。此函數(shù)返回 xml 值。XML 架構(gòu)包括下列信息:
- 事件時間。
- 在執(zhí)行觸發(fā)器時,連接的系統(tǒng)進(jìn)程 ID (SPID)。
- 激發(fā)觸發(fā)器的事件類型。
根據(jù)事件類型,該架構(gòu)還包括其他信息,例如事件在其中發(fā)生的數(shù)據(jù)庫、發(fā)生事件的相關(guān)對象以及事件的 Transact-SQL 語句。
??只有直接在 DDL 或登錄觸發(fā)器內(nèi)部引用 EVENTDATA 時,EVENTDATA 才會返回數(shù)據(jù)。如果 EVENTDATA 由其他例程調(diào)用(即使這些例程由 DDL 或登錄觸發(fā)器進(jìn)行調(diào)用),將返回 NULL。在隱式或顯式調(diào)用 EVENTDATA 的事務(wù)提交或回滾之后,EVENTDATA 所返回的數(shù)據(jù)將無效。
??由于EVENTDATE返回的是xml,所以要對xml進(jìn)行解析。所幸,SQL Server提供了XQuery。XQuery 是一種可以查詢結(jié)構(gòu)化或半結(jié)構(gòu)化 XML 數(shù)據(jù)的語言,基于XPath,并支持更好的迭代、更好的排序結(jié)果以及構(gòu)造必需的 XML 的功能。詳情請參閱:https://msdn.microsoft.com/zh-cn/library/ms190798(v=sql.105).aspx
如果需要返回事件數(shù)據(jù),我們建議使用 XQuery value() 方法而不是 query() 方法。query() 方法可在輸出中返回 XML 和以“and”符轉(zhuǎn)義的回車符和換行符 (CR/LF) 實例,而 value() 方法無法在輸出中呈現(xiàn) CR/LF 實例。
下面提供一些常用的解析:
-- 受影響的時間
@data.value('(/EVENT_INSTANCE/PostTime)[1]', 'sysname')
-- 受影響的服務(wù)器名
@data.value('(/EVENT_INSTANCE/ServerName)[1]', 'sysname')
-- 受影響的登陸名
@data.value('(/EVENT_INSTANCE/LoginName)[1]', 'sysname')
-- 受影響的用戶名
@data.value('(/EVENT_INSTANCE/UserName)[1]', 'sysname')
-- 受影響的數(shù)據(jù)庫名
@data.value('(/EVENT_INSTANCE/DatabaseName)[1]', 'sysname')
-- 受影響的架構(gòu)名
@data.value('(/EVENT_INSTANCE/SchemaName)[1]', 'sysname')
-- 受影響的表名
@data.value('(/EVENT_INSTANCE/ObjectName)[1]', 'sysname')
-- 受影響的sql語句
@data.value('(/EVENT_INSTANCE/TSQLCommand)[1]', 'nvarchar(max)')
-- 事件類型
@data.value('(/EVENT_INSTANCE/EventType)[1]', 'sysname')
創(chuàng)建DDL觸發(fā)器
CREATE TIGGER <觸發(fā)器名>
ON ALL SERVER|DATABASE
[WITH ENCRYPTION]
FOR|AFTER <事件類型或事件組>[,...,n]
[INSERT][,][UPDATE][,][DELETE]
AS
<T-SQL語句或語句塊>
- ALL SERVER:指定DDL觸發(fā)器的作用域為當(dāng)前服務(wù)器。如果指定了此參數(shù),則只要當(dāng)前服務(wù)器中的任何位置上出現(xiàn)命令中指定的事件類型或事件組,就會激發(fā)該觸發(fā)器。創(chuàng)建的觸發(fā)器可在“SQL Server實例→服務(wù)器對象→觸發(fā)器”窗格中顯示。
- DATABASE:指定DDL觸發(fā)器的作用域為當(dāng)前數(shù)據(jù)庫。如果指定了此參數(shù),則只要當(dāng)前數(shù)據(jù)庫中出現(xiàn)命令中指定的事件類型或事件組,就會激發(fā)該觸發(fā)器。創(chuàng)建的觸發(fā)器可在“SQL Server實例→數(shù)據(jù)庫→(數(shù)據(jù)庫名稱)→可編程性→數(shù)據(jù)庫觸發(fā)器”窗格中顯示。
- 事件類型:將激活DDL觸發(fā)器的T-SQL事件的名稱。
- 事件組:預(yù)定義的T-SQL語句事件分組名稱。執(zhí)行任何屬于事件組的T-SQL語句事件之后,都將激發(fā)DDL觸發(fā)器。
【示例】
A、運用具有數(shù)據(jù)庫范圍的 DDL 觸發(fā)器
下面的示例使用 DDL 觸發(fā)器來防止從數(shù)據(jù)庫中刪除任何同義詞。
IF EXISTS (SELECT * FROM sys.triggers
WHERE parent_class = 0 AND name = 'safety')
DROP TRIGGER safety
ON DATABASE;
GO
CREATE TRIGGER safety
ON DATABASE
FOR DROP_SYNONYM
AS
RAISERROR ('You must disable Trigger "safety" to drop synonyms!',10, 1)
ROLLBACK
GO
B、運用具有服務(wù)器范圍的 DDL 觸發(fā)器
在以下示例中,如果當(dāng)前服務(wù)器實例上出現(xiàn)任何 CREATE DATABASE 事件,則使用 DDL 觸發(fā)器輸出一條消息,并使用 EVENTDATA 函數(shù)檢索對應(yīng) Transact-SQL 語句的文本。
IF EXISTS (SELECT * FROM sys.server_triggers
WHERE name = 'ddl_trig_database')
DROP TRIGGER ddl_trig_database
ON ALL SERVER;
GO
CREATE TRIGGER ddl_trig_database
ON ALL SERVER
FOR CREATE_DATABASE
AS
PRINT 'Database Created.'
SELECT EVENTDATA().value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','nvarchar(max)')
GO
C、創(chuàng)建事件數(shù)據(jù)在 DDL 觸發(fā)器中的日志表
CREATE TABLE ddl_log (
PostTime datetime,
DB_User nvarchar(100),
Event nvarchar(100),
TSQL nvarchar(2000))
GO
CREATE TRIGGER log
ON DATABASE
FOR DDL_DATABASE_LEVEL_EVENTS
AS
DECLARE @data XML;
SET @data = EVENTDATA();
INSERT ddl_log (PostTime, DB_User, Event, TSQL)
VALUES
(GETDATE(),
CONVERT(nvarchar(100), CURRENT_USER),
@data.value('(/EVENT_INSTANCE/EventType)[1]', 'nvarchar(100)'),
@data.value('(/EVENT_INSTANCE/TSQLCommand)[1]', 'nvarchar(2000)') ) ;
GO
登錄觸發(fā)器
登錄觸發(fā)器將為響應(yīng) LOGON 事件而執(zhí)行存儲過程。與 SQL Server 實例建立用戶會話時將引發(fā)此事件。登錄觸發(fā)器將在登錄的身份驗證階段完成之后且用戶會話實際建立之前激發(fā)。如果身份驗證失敗,將不激發(fā)登錄觸發(fā)器。
??在登錄觸發(fā)器中不支持分布式事務(wù)。在激發(fā)包含分布式事務(wù)的登錄觸發(fā)器時,將返回錯誤 3969。
【示例】
下面的登錄觸發(fā)器示例拒絕了作為 login_test 登錄名的成員登錄 SQL Server 的嘗試(如果在此登錄名下已運行三個用戶會話)。
USE master;
GO
CREATE LOGIN login_test WITH PASSWORD = '3KHJ6dhx(0xVYsdf' MUST_CHANGE,
CHECK_EXPIRATION = ON;
GO
GRANT VIEW SERVER STATE TO login_test;
GO
CREATE TRIGGER connection_limit_trigger
ON ALL SERVER WITH EXECUTE AS 'login_test'
FOR LOGON
AS
BEGIN
IF ORIGINAL_LOGIN()= 'login_test' AND
(SELECT COUNT(*) FROM sys.dm_exec_sessions
WHERE is_user_process = 1 AND
original_login_name = 'login_test') > 3
ROLLBACK;
END;
管理觸發(fā)器
①查看觸發(fā)器信息
因為觸發(fā)器是特殊的存儲過程,所以查看觸發(fā)器也是使用系統(tǒng)存儲過程實現(xiàn),如:
sp_help '觸發(fā)器名稱'
sp_helptext '觸發(fā)器名稱'
sp_depends '觸發(fā)器名稱'|'表名'
②修改觸發(fā)器
1、修改DML觸發(fā)器
ALTER TIGGER <觸發(fā)器名>
ON <表名|視圖名>
[WITH ENCRYPTION]
FOR|AFTER|INSTEAD OF
[INSERT][,][UPDATE][,][DELETE]
AS
<T-SQL語句或語句塊>
2、修改DDL觸發(fā)器
ALTER TIGGER <觸發(fā)器名>
ON ALL SERVER|DATABASE
[WITH ENCRYPTION]
FOR|AFTER <事件類型或事件組>[,...,n]
[INSERT][,][UPDATE][,][DELETE]
AS
<T-SQL語句或語句塊>
;
③刪除觸發(fā)器
-- Trigger on an INSERT, UPDATE, or DELETE statement to a table or view (DML Trigger)
DROP TRIGGER [ IF EXISTS ] [schema_name.]trigger_name [ ,...n ]
-- Trigger on a CREATE, ALTER, DROP, GRANT, DENY, REVOKE or UPDATE statement (DDL Trigger)
DROP TRIGGER [ IF EXISTS ] trigger_name [ ,...n ] ON { DATABASE | ALL SERVER }
-- Trigger on a LOGON event (Logon Trigger)
DROP TRIGGER [ IF EXISTS ] trigger_name [ ,...n ] ON ALL SERVER
④禁用與啟用觸發(fā)器
#禁用觸發(fā)器
DISABLE TIGGER <觸發(fā)器名> ON 對象名|DATABASE|ALL SERVER
#啟用觸發(fā)器
ENABLE TIGGER <觸發(fā)器名> ON 對象名|DATABASE|ALL SERVER