监测数据库的结构变化

有时候,一个项目里有很多人都有权限修改数据库的结构,就会造成,一个人更改了表结构,而其他开发者不知道的情况。为了记录那些人对哪些结构进行了修改。下面有一段脚本可以记录修改活动。

首先 创建一个表,用来记录 修改的活动。

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[ddl_log](
    [log_id] [int] IDENTITY(1,1) NOT NULL,
    [post_time] [datetime] NULL,
    [server_name] [varchar](100) NULL,
    [database_name] [varchar](100) NULL,
    [login_name] [varchar](100) NULL,
    [target_object_name] [varchar](100) NULL,
    [event_type] [varchar](100) NULL,
    [command_text] [varchar](8000) NULL,
    [client_host_name] [varchar](128) NULL,
    [client_ip] [varchar](20) NULL,
    [client_mac] [varchar](20) NULL,
    [client_program_name] [nvarchar](128) NULL,
    [event_instance] [xml] NULL,
PRIMARY KEY CLUSTERED
(
    [log_id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

 

接着 写一个触发器,将对数据库结构的修改行为记录紧 上面的表中。

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

create trigger [ddl_trigger_database]
    on database
    for ddl_database_level_events
as
    declare @data xml,
    @post_time datetime,           --创建时间
    @server_name varchar(100),         --服务器名
    @databasename varchar(100),        --数据库名称
    @login_name varchar(100),          --登录用户名称
    @target_object_name varchar(100),  --触发对象名称
    @event_type varchar(100),          --事件类型
    @command_text varchar(8000),       --执行代码
    @client_host_name varchar(128),    --工作站名称
    @client_ip varchar(20),            --客户端ip地址
    @client_mac varchar(20),        --客户端mac地址
    @client_program_name nvarchar(128) --客户端应用程序   

    set @data=EVENTDATA()    

    --path 区分大小写
    set @databasename=@data.value('(/EVENT_INSTANCE/DatabaseName)[1]','varchar(100)')
    set @target_object_name=@data.value('(/EVENT_INSTANCE/ObjectName)[1]','varchar(100)')
    if lower(@target_object_name)='ddl_log' and @data.value('(/EVENT_INSTANCE/ObjectType)[1]','varchar(100)')='TABLE'

    begin     

       raiserror('deleted or alter table ddl_log fail.', 16, -1)
       rollback transaction
       return
    end   

    set @post_time=@data.value('(/EVENT_INSTANCE/PostTime)[1]','datetime')
    set @server_name=@data.value('(/EVENT_INSTANCE/ServerName)[1]','varchar(100)')  
    set @login_name=@data.value('(/EVENT_INSTANCE/LoginName)[1]','varchar(100)')
    set @event_type=@data.value('(/EVENT_INSTANCE/EventType)[1]','varchar(100)')
    set @command_text=@data.value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','varchar(8000)')
    set @command_text=ltrim(rtrim(replace(replace(@command_text,char(10),' '),char(13),' ')))  --换行替换为空格
    select @client_ip = client_net_address from sys.dm_exec_connections where session_id = @@spid  
    select @client_program_name = program_name,@client_host_name=host_name from  sys.dm_exec_sessions  where session_id = @@spid
    select @client_mac = net_address from master.dbo.sysprocesses where spid = @@spid
    insert into [ddl_log]
          ([post_time]
          ,[server_name]
          ,[database_name]
          ,[login_name]
          ,[target_object_name]
          ,[event_type]
          ,[command_text]
          ,[client_host_name]
          ,[client_ip]
          ,[client_mac]
          ,[client_program_name]
          ,[event_instance])
    values
       (@post_time
       ,@server_name
       ,@databasename
       ,@login_name
       ,@target_object_name
       ,@event_type
       ,@command_text
       ,@client_host_name
       ,@client_ip
       ,@client_mac
       ,@client_program_name
       ,@data)


GO

SET ANSI_NULLS OFF
GO

SET QUOTED_IDENTIFIER OFF
GO

DISABLE TRIGGER [ddl_trigger_database] ON DATABASE
GO

ENABLE TRIGGER [ddl_trigger_database] ON DATABASE
GO

这样通过查询 第一步中的表,就可查看,哪些用户对数据库执行了哪些操作了。

哈哈。

posted @ 2012-03-16 16:44  doo  阅读(647)  评论(0编辑  收藏  举报