1. 程式人生 > >SQL Server DDL觸發器

SQL Server DDL觸發器

用戶名 eat exists lar value back ref tro get

DDL 觸發器作用:

DDL 觸發器主要用於防止對數據庫架構、視圖、表、存儲過程等進行的某些修改。

DDL 觸發器事件:

DDL 觸發器在創建用來監視並響應該數據庫或服務器實例中的活動的事件通知時,可以指定相應事件類型或事件組。

超鏈接:DDL 事件 和 DDL 事件組

DDL 觸發器類別:

DDL 觸發器分為:數據庫(DataBase)級別和服務器(Server)級別

DDL 數據庫(DataBase)級別觸發器:

因為 DDL 觸發器不在架構範圍內,所以不會在 sys.objects 目錄視圖中出現,無法使用 OBJECT_ID 函數來查詢數據庫中是否存在 DDL 觸發器。
可以使用相應的目錄視圖來查詢架構範圍以外的對象。

對於 DDL 數據庫級別觸發器,可使用 sys.triggers 視圖。對於 DDL 服務器級別觸發器,可使用 sys.server_triggers 視圖。

創建一個修改和刪除表(table)的 DDL 數據庫級別觸發器:

技術分享圖片
-- 判斷名為 trigger_DDL_Table 的數據庫級別的觸發器是否存在
if exists(select * from sys.triggers where parent_class=0 and name=‘trigger_DDL_Table‘)

drop trigger trigger_DDL_Table on database        --刪除名為 trigger_DDL_Table 的數據庫級別的觸發器
go
create trigger trigger_DDL_Table    -- 創建觸發器
on database
for drop_table,alter_table        -- 指定觸發器事件
as
    
    print ‘觸發器 trigger_DDL_Table 已禁止對表進行DDL的 drop、alter 操作‘
    rollback    --對操作進行回滾
go

drop table Student_back

alter table Student_back add cc int null default(1)
技術分享圖片

技術分享圖片

創建一個在工作時間不允許創建、修改和刪除視圖(view)的 DDL 數據庫級別觸發器:

技術分享圖片
-- 判斷名為 trigger_DDL_View 的數據庫級別的觸發器是否存在
if exists(select * from sys.triggers where parent_class=0 and name=‘trigger_DDL_View‘)

drop trigger trigger_DDL_View on database        --刪除名為 trigger_DDL_View 的數據庫級別的觸發器
go
create trigger trigger_DDL_View    -- 創建觸發器
on database
for create_view,drop_view,alter_view        -- 指定觸發器事件
as
    if(DATEPART(hour,getdate()) between 9 and 17)
    begin
        declare @EventData xml
        set @EventData=EVENTDATA();

        select ‘觸發器 trigger_DDL_View 已禁止工作時間對視圖進行DDL的 create、drop、alter 操作‘

        select @EventData.value(‘(/EVENT_INSTANCE/EventType)[1]‘,‘nvarchar(max)‘) as EventType,    --事件類型
               @EventData.value(‘(/EVENT_INSTANCE/PostTime)[1]‘,‘nvarchar(max)‘) as PostTime,    --事件觸發的時間
               @EventData.value(‘(/EVENT_INSTANCE/DatabaseName)[1]‘,‘nvarchar(max)‘) as DatabaseName,    --數據庫名
               @EventData.value(‘(/EVENT_INSTANCE/ObjectName)[1]‘,‘nvarchar(max)‘) as ObjectName,    --操作的對象名稱
               @EventData.value(‘(/EVENT_INSTANCE/ObjectType)[1]‘,‘nvarchar(max)‘) as ObjectType,    --操作的對象類型
               @EventData.value(‘(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]‘,‘nvarchar(max)‘) as CommandText    --操作命令文本

        rollback    --對操作進行回滾,也可以不回滾
    end
go

drop view v_Stu_Cou        -- 刪除視圖
技術分享圖片

技術分享圖片

啟用和禁用數據庫級別觸發器:

-- 啟用名為 trigger_DDL_View 的數據庫級別觸發器  
enable trigger trigger_DDL_View on database;

-- 禁用名為 trigger_DDL_View 的數據庫級別觸發器 
disable trigger trigger_DDL_View on database;  

查看數據庫級別的觸發器及事件:

技術分享圖片
--數據庫級別觸發器視圖
select * from sys.triggers

--數據庫級別觸發器事件視圖
select * from sys.trigger_events

--查看數據庫級別的觸發器及事件  
select a.name,a.parent_class_desc,b.type_desc  
from sys.triggers a 
inner join sys.trigger_events b  
on a.object_id=b.object_id 
技術分享圖片

EVENTDATA( ) 函數:可以在觸發器內部(即 create 的 T-SQL 中)使用,當事件觸發時,該函數返回一個 XML 數據類型,其中包含觸發器的事件信息。

-- 當觸發器執行時,該函數會返回觸發器的事件信息。
 select EVENTDATA();

技術分享圖片

當返回 XML 類型的結果,可以點擊進行查看:

技術分享圖片
 1 <EVENT_INSTANCE>
 2   <EventType>DROP_VIEW</EventType>  -- 事件類型
 3   <PostTime>2017-04-23T16:29:58.130</PostTime> -- 事件執行時間
 4   <SPID>52</SPID>  
 5   <ServerName>DESKTOP-LQUB0OA</ServerName>  -- 計算機名稱
 6   <LoginName>sa</LoginName>  -- 登陸用戶名
 7   <UserName>dbo</UserName>  -- 用戶(即所有者)
 8   <DatabaseName>Test</DatabaseName>  -- 數據庫名
 9   <SchemaName>dbo</SchemaName>  -- 所有者
10   <ObjectName>v_Stu_Cou</ObjectName>  -- 對象名
11   <ObjectType>VIEW</ObjectType>  --對象類型
12   <TSQLCommand>  -- T-SQL 命令
13     <SetOptions ANSI_NULLS="ON" ANSI_NULL_DEFAULT="ON" ANSI_PADDING="ON" QUOTED_IDENTIFIER="ON" ENCRYPTED="FALSE" />
14     <CommandText>drop view v_Stu_Cou        -- 刪除視圖</CommandText>  -- 命令文本
15   </TSQLCommand>
16 </EVENT_INSTANCE>
技術分享圖片

更多關於 EVENTDATA() 函數請參考:

https://docs.microsoft.com/en-us/sql/t-sql/functions/eventdata-transact-sql

DDL 服務器(Server)級別觸發器:

創建一個創建、修改、刪除數據庫的服務器級別觸發器:

技術分享圖片
-- 判斷名為 trigger_DDL_DB 的服務器級別的觸發器是否存在,註意這裏使用的是 sys.server_triggers 這個視圖
if exists(select * from sys.server_triggers where name=‘trigger_DDL_DB‘)

drop trigger trigger_DDL_DB on all server        --刪除名為 trigger_DDL_DB 的服務器級別的觸發器
go
create trigger trigger_DDL_DB    -- 創建觸發器
on all server
for create_database,drop_database,alter_database        -- 指定觸發器事件
as
    declare @EventData xml
    set @EventData=EVENTDATA();

    -- 當觸發器執行時,該函數會返回觸發器的事件信息。
    select EVENTDATA();

    select ‘觸發器 trigger_DDL_DB 已禁止創建、修改、刪除數據庫操作‘

    select @EventData.value(‘(/EVENT_INSTANCE/EventType)[1]‘,‘nvarchar(max)‘) as EventType,    --事件類型
            @EventData.value(‘(/EVENT_INSTANCE/PostTime)[1]‘,‘nvarchar(max)‘) as PostTime,    --事件觸發的時間
            @EventData.value(‘(/EVENT_INSTANCE/ServerName)[1]‘,‘nvarchar(max)‘) as ServerName,    --計算機名
            @EventData.value(‘(/EVENT_INSTANCE/DatabaseName)[1]‘,‘nvarchar(max)‘) as DatabaseName,    --數據庫名
            @EventData.value(‘(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]‘,‘nvarchar(max)‘) as CommandText    --操作命令文本

    rollback    --對操作進行回滾,也可以不回滾
go

create database Demo        -- 創建數據庫
    on primary 
    (   
        name = N‘DemoDB_Data‘,   
        filename = N‘D:\DemoDB_Data.mdf‘,   
        size = 5mb,   
        maxsize = unlimited,
        filegrowth = 5%   
    )
    log on
     (
         name=N‘DemoDB_log‘,        
         filename=N‘D:\DemoDB_log.ldf‘,   
         size = 2mb,           
         maxsize = unlimited,        
         filegrowth = 1%        
     )
技術分享圖片

技術分享圖片

啟用和禁用服務器級別觸發器:

-- 啟用名為 trigger_DDL_DB 的服務器級別觸發器  
enable trigger trigger_DDL_DB on all server;

-- 禁用名為 trigger_DDL_DB 的服務器級別觸發器 
disable trigger trigger_DDL_DB on all server;  

查看服務器級別觸發器及事件:

技術分享圖片
--服務器級別的觸發器視圖
select * from sys.server_triggers

--服務器級別的觸發器事件視圖
select * from sys.server_trigger_events

--查看服務器級別的觸發器及事件  
select a.name,a.parent_class_desc,b.type_desc  
from sys.server_triggers a 
inner join sys.server_trigger_events b  
on a.object_id=b.object_id  
技術分享圖片

參考:

http://www.cnblogs.com/qanholas/archive/2012/05/10/2494643.html

https://msdn.microsoft.com/zh-cn/library/ms190989(v=sql.100).aspx

SQL Server DDL觸發器