使用Server Trigger保护重要的数据库对象

一 .Server Trigger的简单介绍

sql Server数据库中,Server Trigger 是一种特殊类型的存储过程它可以对特定表、视图或存储中的必然事件自动响应,不由用户调用。创建触发器时对其进行定义,以便在对特定的数据库对象作特定类型的修改时执行,根据触发器定义的动作做出反应。

其主要被用在保持数据库对象的完整性方面。例如,防止数据库中已建好的表和存储过程被更改或删除。此外还可以 进行更改历史记录的追踪,查看表或存储被修改的记录。

Server Trigger比Database Trigger所管控的范围更广,可以管控Server下的所有Database的对象。

 

二. 主要表 及创建脚本

表Protected_Objects ,主要用来存储被保护的数据库对象,例如 表和存储过程。 字段 ActiveFlag设置为Y时有效,N是无效。

有新的数据库对象创建,最自动Insert一笔数据。

CREATE TABLE [dbo].Protected_Objects](
    ServerIP] varchar](100) NULL,ServerNamedbnameObjNameObjtypeCreatorActiveFlag10) TransDateTimedatetime] 
) ON PRIMARY]

GO

 

表DBTrigger_Log,主要存储数据库对象变动记录。

 

DBTrigger_Log20) 50) ObjectNameObjectTypeEventTypeHostName128) AppNameEventDataxmlFlagintNULL DEFAULT ((0))
) ] TEXtimage_ON GO

SET ANSI_PADDING OFF
EXEC sys.sp_addextendedproperty @name=N'MS_Description',@value服务器IP@level0typeSCHEMA@level0name@level1typeTABLE@level1name@level2typeCOLUMN@level2name'
服务器名称数据库名称对象名称对象类型事件类型终端机器名名称触发事件xml发生时间是否上传GO

 

三. 创建Server Trigger的脚本

 

USE master]
/****** Object:  DdlTrigger [ServerDBTrigger_ProtectObjects]    Script Date: 2018/12/27 13:36:00 ******/
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER GO


###########################################################################################
*Program*:            <DB Trigger>
*Description*:        <Protect sql key objects>
*programer*:         <>
*Date*:             2015-12-03

---0001  2015-12-03  11:12      第一阶段期间只保留修改记录,暂时不阻止(不RollBack) 
---0002  2015-12-03  15:32      增加邮件功能.  
---0003  2015-12-04  14:20      出现set ANSI_PADDING Off后,还有(如果是script出来的表,其中有索引约束等,
---                             需要Alter表时,就会报错。)代码时,@xEvent.query会报错。
##############################################################################################TRIGGER ServerDBTrigger_DBA_ProtectObjectsON ALL SERVER
FOR DROP_TABLE,DROP_PROCEDURE,DROP_VIEW,DROP_FUNCTION,CREATE_TABLE,CREATE_PROCEDURE,CREATE_VIEW,CREATE_FUNCTION,ALTER_PROCEDURE,ALTER_VIEW,ALTER_TABLE,ALTER_FUNCTION,RENAME

AS
  SET NOCOUNT ON ;
  BEGIN TRY

    DECLARE @ServerIP varchar(20)
    @ServerName 50@AppName nvarchar(128@HostName @dbname 100@ObjectName @ObjectType @EventType @ObjectAction @xEvent XML
    SET @xEvent = EVENTDATA()
    ----------------------0003 start ----------
    Set @dbname=CONVERT(VARCHAR(100),@xEvent.query('data(/EVENT_INSTANCE/DatabaseName)'))
    Set @ObjectName=CONVERT(VARCHAR(100),@xEvent.query('data(/EVENT_INSTANCE/ObjectName)'))
    Set @ObjectType=CONVERT(VARCHAR(100),@xEvent.query('data(/EVENT_INSTANCE/ObjectType)'))
    Set @ObjectAction=CONVERT(VARCHAR(100),@xEvent.query('data(/EVENT_INSTANCE/EventType)'))
    @EventData varchar(MAXSELECT @EventData=CONVERT(VARCHAR(MAX),1)">@dbname= SUBSTRING (@EventData,CHARINDEX(<DatabaseName>@EventData)+14,1)"></DatabaseName>--14@ObjectName<ObjectName>12,1)"></ObjectName>12@ObjectType<ObjectType></ObjectType>@ObjectAction<EventType>11,1)"></EventType>11@EventTypeSUBSTRING(----------0003 end ---------------
    @HostNameHOST_NAME(),1)">@AppNameAPP_NAME()
    SELECT  @ServerName = @@SERVERNAME
    @ServerIP MIN(LOCAL_NET_ADDRESS) FROM SYS.DM_EXEC_CONNECTIONS WHERE LOCAL_NET_ADDRESS IS NOT NULL
    IF EXISTS(TOP 1 ObjName FROM Protected_Objects WITH(NOLOCK) WHERE ServerName @@SERVERNAME AND dbname@dbname AND ObjName@ObjectName AND ActiveFlagY'BEGIN
        IF (LIKE TMP%')OR (@ObjectAction LIKE 'ALTER%' AND */[_]%)
         BEGIN
            INSERT  INTO  DBTrigger_Log
                                ( ServerIP,ServerName,dbname,ObjectName,ObjectType,EventType,HostName,AppName,TransDateTime)
                        VALUES  ( @ServerIP,1)">@ServerName,1)">@dbname,1)">@ObjectName,1)">@ObjectType,1)">@EventType,1)">@HostName,1)">@AppName,1)">GETDATE())
         END
        ELSE 
         BEGIN 
         
            ---------------0001 start ---
            ())
            
            Rollback TRANSACTION
            ---------------end --------
            -----------0002 begin ----------------
              
            @Subject AS 200)
            @Body nvarchar(@SPName )
            
            @Subject ServerDBTrigger-重要!;ServerIP:' + @ServerIP
                        @SPName ''
                        @Body <html><body>Dear All,<br> <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServerName:@ServerName+  ; ServerIP:@ServerIP上的object已被改动,请及时检查!!!
                       <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;You can get detail information from DBA_DBTrigger_Log. <br><br><table border=1 bgcolor=#aaff11>' 
                        @Body<tr bgcolor=#ffaa11><td>ServerName</td><td>ServerIP</td><td>dbname</td><td>EventType</td><td>ObjectName</td><td>ObjectType</td><td>HostName </td><td>TransDateTime</td></tr>'
                        <tr bgcolor=#ffaa11><td>'CAST(NVARCHAR(50))</td><td>50)) +20))SUBSTRING(REPLACE(500)),1)">CHAR(0),1)">''),1,1); font-weight: bold">500)100),1)">GETDATE(),1); font-weight: bold">21)</td></tr></table>'

            @BODYREPLACE(@BODY,1)">'''',1)">'')

            IF ' '')<>''
                BEGIN
                    @AllEmailToAddress 3000)''
                    @AllEmailCcAddress @Allprofile_name 100)@AllEmailToAddress收件人的地址'
                    @AllEmailCcAddress抄送人的地址'

                    1 @Allprofile_name=NAME FROM msdb.dbo.sysmail_profile ORDER BY profile_id

                    EXEC msdb..sp_send_dbmail @profile_name @Allprofile_name      profile 名称 ,1)">@recipients   =  @AllEmailToAddress          收件人邮箱 ,1)">@copy_recipients@AllEmailCcAddress@subject      @Subject                    邮件标题 ,1)">@body         @BODY                       邮件内容 ,1)">@body_format  =  HTML'                      邮件格式 ,1)">@file_attachmentsEND     
              -----------    0002 end ------------
            
         END            
    END
    --新建对象自动塞入保护表
    ELSE 
    PRINT 3 
        DELETE @ObjectName
        IF @ObjectAction Create%AND @AppName %Microsoft sql Server Management Studio%' 
            NOT '
        BEGIN 
             Protected_Objects
                        () )
            ())
        END 
        ELSE IF  '  '    
        ())

        END     
END TRY
 CATCH
    PRINT @ObjectName:+@ObjectName
    @ObjectType:@ObjectType
    PRINT ERROR_MESSAGE()
    ROLLBACK TRANSACTION
 CATCH

OFF


GO

ENABLE ServerDBTrigger_ProtectObjectsGO

 

四. 补充

创建Server Trigger 后,此时表Protected_Objects是空的,没有被保护的数据库对象。我们可以将数据库下面的对象批量插入。例如,我们将数据库XXXX下除 _和unuse开头之外的所有对象批量插入。其脚本如下:

INSERT  Protected_Objects(dbname,ObjName,ObjType,Creator,ActiveFlag,TransDateTime)
SELECT XXXXXXCASE xtype WHEN U' THEN TablePProcedureFNFunctionTFVViewVARCHAR(10),1)">DATEADD(DAY,1); font-weight: bold">46,1)">GETDATE()),1); font-weight: bold">120)
FROM XXXXXXX].dbo.sysobjects WHERE xtype IN ()  
    AND  name ' 
    AND name unuse%'

 

相关文章

SELECT a.*,b.dp_name,c.pa_name,fm_name=(CASE WHEN a.fm_n...
if not exists(select name from syscolumns where name=&am...
select a.*,pano=a.pa_no,b.pa_name,f.dp_name,e.fw_state_n...
要在 SQL Server 2019 中设置定时自动重启,可以使用 Window...
您收到的错误消息表明数据库 &#39;EastRiver&#39; 的...
首先我需要查询出需要使用SQL Server Profiler跟踪的数据库标...