觸發(fā)器

觸發(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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,739評論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,634評論 3 419
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,653評論 0 377
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,063評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,835評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,235評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,315評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,459評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,000評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,819評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,004評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,560評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,257評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,676評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,937評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,717評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,003評論 2 374

推薦閱讀更多精彩內(nèi)容

  • 1.1 基本結(jié)構(gòu) PL/SQL程序由三個塊組成,即聲明部分、執(zhí)行部分、異常處理部分。 1.2 命名規(guī)則 1.3 記...
    慢清塵閱讀 3,872評論 3 14
  • Classification DML(Data Manipulation Language) Trigger : ...
    FengBli閱讀 540評論 0 0
  • 觸發(fā)器 MySQL包含對觸發(fā)器的支持。觸發(fā)器是一種與表操作有關(guān)的數(shù)據(jù)庫對象,當(dāng)觸發(fā)器所在表上出現(xiàn)指定事件時,將調(diào)用...
    FTOLsXD閱讀 949評論 0 1
  • SQL Server觸發(fā)器創(chuàng)建、刪除、修改、查看示例步驟 一﹕ 觸發(fā)器是一種特殊的存儲過程﹐它不能被顯式地調(diào)用﹐而...
    oo水桶oo閱讀 3,245評論 0 3
  • 1、戰(zhàn)略與企業(yè)戰(zhàn)略 <1>戰(zhàn)略:泛指統(tǒng)領(lǐng)性的,全局性的,左右勝敗的謀略,方案和對策,運用于政治,經(jīng)濟(jì),軍事等領(lǐng)域。...
    D048魔法閱讀 231評論 0 0