用触发器生成数据库表的数据操作日志
来源:天极开发 作者: 出处:综艺读书 2006-11-24·数据库人员面试:SQL Server常用测试题(1
·PHP连接数据库的方法(3)
·InterBase 数据库函数库
·图解MySQL数据库的安装和操作 (1)
·[冷枫推荐]:数据库操作,内外联查询,分
·PHP中使用类对数据库进行操作
·用JSP从数据库中读取图片并显示在网页上
·ACESS数据库与WEB页连接
·DB2 9数据库免费版下载地址
·利用外部命令Oralce数据库导入导出
·PHP连接数据库的方法(3)
·InterBase 数据库函数库
·图解MySQL数据库的安装和操作 (1)
·[冷枫推荐]:数据库操作,内外联查询,分
·PHP中使用类对数据库进行操作
·用JSP从数据库中读取图片并显示在网页上
·ACESS数据库与WEB页连接
·DB2 9数据库免费版下载地址
·利用外部命令Oralce数据库导入导出
作为一名数据库管理员,你尽力以各部门熟知的不同格式,向各部门提供它们所需要的数据。你通常将MS Excel格式的数据递交到会计部门,或将数据以HTML报表的形式呈现给普通用户。你们的系统安全管理员们则习惯于用文本阅读器或者事件查看器来查看日志。本文将介绍如何使用触发器,把DML(数据操作语言)对数据库中的特定数据表的改动记录下来。注:下列例子为Insert型触发器,不过改成Delete/Update型的触发器也很容易。
操作步骤首先让我们在Northwind数据库内创建一个简单表。
| create table tablefortrigger ( track int identity(1,1) primary key, Lastname varchar(25), Firstname varchar(25) ) |
创建好这个数据表后,添加一个标准message到master数据库的sysmessages数据表中。注意,我所添加的是一个参变量,用以接受一个字符值,它将被输出显示给管理员们。通过设置@_with_log参数为true,我们包管相关结果被发送到事件日志。
| sp_addmessage 50005, 10, '%s', @with_log = true |
现在我们创建这条用有意义的信息填充的消息。下面的信息将填充这条消息,并且记录到文件中:
·操作的类型(插入)。
·受到影响的数据表。
·改动的日期与时间。
被该语句插入的全部字段。 下面的这个触发器用预定义值(1~3个字符)创建一个字符串,该预定义值位于inserted数据表中。(这个inserted数据表驻留在内存中,它容纳被插入到触发器所在数据表的记录行)。触发器连接这些值并放到一个@msg变量。然后这个变量被传送到raiserror函数,该函数将它写到事件日志中。
| Create trigger TestTrigger on tablefortrigger for insert as --声明储存消息的变量 Declare @Msg varchar(8000) --将"操作/表名/日期时间/插入字段"赋与消息 set @Msg = 'Inserted | tablefortrigger | ' + convert(varchar(20), getdate()) + ' | ' +(select convert(varchar(5), track) + ', ' + lastname + ', ' + firstname from inserted) --产生错误发送给事件查看器。 raiserror( 50005, 10, 1, @Msg) |
运行以下语句对触发器进行测试,然后查看事件日志:
| Insert into tablefortrigger(lastname, firstname) Values('Doe', 'John') |
如果你打开事件日志,你应该看到以下消息:
既然我们已经有办法写入事件日志了,那么让我们修改一下触发器,将数据写到一个文本文件中。这次改动还须添加另一个变量@CmdString,以及使用扩展储存过程xp_cmdshell。
因为我们要写入文件系统,安全权限开始有影响了。所以,执行插入操作的用户必须具备该文本文件的读写权限。因此,设计一个C/S结构的应用程序供多用户运行,或许不是一个可行的解决方案。更合理的方案是,设计一个三层应用程序,由你的中间层组件对单用户数据库进行调用。在后一个方案中,对那个文本文件的权限管理其实比管理一个用户还容易。
| Alter trigger TestTrigger on tablefortrigger for insert as Declare @Msg varchar(1000) --储存将由xp_cmdshell执行的命令 Declare @CmdString varchar (2000) set @_msg = ' insert | tablefortrigger | ' + convert ( varchar ( 20 ) , getdate ( ) ) + ' | ' + ( select convert ( varchar ( 5 ) , track ) + ' , ' + lastname + ' , ' + firstname from insert ) - [99%]set @Msg = 'Inserted | tablefortrigger | ' + convert(varchar(20), getdate()) + ' | ' +(select convert(varchar(5), track) + ', ' + lastname + ', ' + firstname from inserted) --产生错误发送给事件查看器。 raiserror( 50005, 10, 1, @Msg) set @CmdString = 'echo ' + @Msg + ' >> C:\logtest.log' --写到文本文件 exec master.dbo.xp_cmdshell @CmdString |
让我们对它进行测试,先运行前面的插入语句,然后打开C:\logtest.log文件查看结果:
| Insert into tablefortrigger(lastname, firstname) Values('Doe', 'John') |
问题解决了,对不对?哦,还没完全解决。发生多次重复插入的事件是什么原因?在这个例子中,你必须分别地处理每条记录。为了达到这个目的,我们必须用一个会带来麻烦的游标来访问"隐蔽面"。在执行以前,我必须预先给予警告。你应当了解的是,当这个应用程序进行大规模地记录插入、更新或删除时要当心,因为它可能会耗费大量的内存。
像你从下面看到的一样,这次我们在前面那个例子的基础上稍加调整,引入了一个游标,对该插入表的全部记录进行循环读取。每条记录分别插入一条线条,将各个事件区分开来。
| ALTER trigger TestTrigger on tablefortrigger for insert as Declare @Msg varchar(1000) Declare @CmdString varchar (1000) Declare GetinsertedCursor cursor for Select 'Inserted | tablefortrigger | ' + convert(varchar(20), getdate()) + ' | ' + convert(varchar(5), track) + ', ' + lastname + ', ' + firstname from inserted open GetinsertedCursor Fetch Next from GetinsertedCursor into @Msg while @@fetch_status = 0 Begin raiserror( 50005, 10, 1, @Msg) Fetch Next from GetinsertedCursor into @Msg set @CmdString = 'echo ' + @Msg + ' >> C:\logtest.log' exec master.dbo.xp_cmdshell @CmdString End close Getinsertedcursor deallocate GetInsertedCursor |
现在让我们执行重复多次插入测试:
| Insert into tablefortrigger(lastname, firstname) Select lastname, firstname from employees |
结论
在继续完成之前,有些人认为必须考虑性能与安全问题。你将看到写入文本文件的开销,而对于一个每分钟处理5000项事务的数据库来说,这样大的开销也许不可接受。由于xp_cmdshell是在SQL外操作的,写入到文件的错误不会回滚事务。倘若入侵者使用一个隐蔽的途径来改变你的数据,这个事件不会被登记到那个文本文件中。不过事件日志将记录该次DML改动。作为一次最好的实践,各事件的编号应该被用于对照日志文件的各行记录,以便发现所有的差异。
有很多种方法可以达到本文目标,上述脚本也可以有许多的变化。我希望你能接受这个脚本,然后作出改进并提出建议,使它更有效率。
相关图文阅读
频道图文推荐
相关专题
·数据库专栏 (4469篇文章)
·数据库处理专题 (7214篇文章)
·城域网专题 (6668篇文章)
·数据库安全技术专题 (11215篇文章)
·Linux日志专题 (7111篇文章)
·数据库安装与卸载 (8929篇文章)
·Linux数据库宝典 (11165篇文章)
·数据库相关文章 (4470篇文章)
·数据库处理专题 (7214篇文章)
·城域网专题 (6668篇文章)
·数据库安全技术专题 (11215篇文章)
·Linux日志专题 (7111篇文章)
·数据库安装与卸载 (8929篇文章)
·Linux数据库宝典 (11165篇文章)
·数据库相关文章 (4470篇文章)
·分析各种数据库优点 帮你做出准确选择 (0次浏览)
·分析各种数据库优点 帮你做出准确选择 (0次浏览)
最新技术文档
·分析各种数据库优点 帮你做出准确选择 06-16
·数据库技术趋势发展三大特征:XML、BI、SOA 05-21
·如何在查询的时候再追加一个字段 04-09
·在多种数据库环境下管理业务需求(下) 03-31
·不同环境下都可以工作的基本备份策略 03-28
·ASP-PHP-JSP-NET-CF 03-26
·ado异步查询的解决方案 03-26
·ADO事件模型 03-26
·ADO连接数据库字符串大全 03-26
·ADO对象中的常量 03-26
·数据库技术趋势发展三大特征:XML、BI、SOA 05-21
·如何在查询的时候再追加一个字段 04-09
·在多种数据库环境下管理业务需求(下) 03-31
·不同环境下都可以工作的基本备份策略 03-28
·ASP-PHP-JSP-NET-CF 03-26
·ado异步查询的解决方案 03-26
·ADO事件模型 03-26
·ADO连接数据库字符串大全 03-26
·ADO对象中的常量 03-26
站内各频道最新更新文档
站内最新制作专题
|
|||
| ·ACDSEE专题教程-下载使用 ·迅雷专题教程-下载使用 ·Windows XP频道 ·Windows Vista频道 ·Windows 2000频道 ·win2003频道 ·Freebsd频道 ·Oracle频道 |
·Linux频道 ·Windows频道 ·邮件服务器专题 ·协议大全 ·数据恢复指南教程 ·FreeBSD使用教程 ·Linux数据库宝典 ·Linux基础知识 |
||
热门关键字导读
站内频道文章精选
| · 秘密:Vista隐蔽的动态屏保 · 腾讯开发新电子宠物--QQ熊 · 惠普否认2999元PC有价无货 |
· 驱逐Win系统“流氓”文件 · WinXP中获取未使用的IP地址 · 尝试format C:格式化硬盘? |
| · 在DOS下恢复回收站中的文件 · 拯救WinXP崩溃的救命稻草 · Linux系统中超级权限的应用 |
· 搜狗PK谷歌:谁能代言拼... · 昨日重现,一键GHOST轻松.. · 实现Web迅雷在空闲时杀毒 |
| · AVIFile函数制做AVI文件 · VC中链接动态链接库的方法 · 熊猫烧香核心源码(Delphi) |
· DateDiff函数祥解 · JavaScript去除空格的三种 · js效果 图片加载进度实时.. |
| · SQL Server数据库优化方案 · Oracle的初学者入门心得 · JSP连接Mysql数据库 |
· Photoshop为美女做艺术处理 · 用Freehand创建发光字特效 · 设计自己的个性QQ动态表情 |
百度推荐,商机无限
搜索您感兴趣的内容





