2009-03-02 32 views
1

我试图通过向我的表添加触发器并将行插入到我的审计表中来执行审计历史记录。我有一个存储过程,使插入更容易一些,因为它节省了代码;我不必写出整个插入语句,而是使用我想要插入的列的几个参数来执行存储过程。在触发器中审计每个插入的行

我不知道如何为“插入”表中的每一行执行存储过程。我想也许我需要使用游标,但我不确定。我以前从未使用过光标。

由于这是一个审计,我将需要比较旧的每列的值,以查看它是否发生了变化。如果确实发生了变化,我将执行向我的审计表添加一行的存储过程。

有什么想法?

+0

您正在使用什么版本的SQL Server?如果SQL 2K8中有一些内置的审计工具必须比您构建的维护更好。 – JohnFx 2009-03-18 14:47:51

回答

1

如果您的数据库需要扩展一些用户,这将变得非常昂贵。我会建议查看第三方数据库审计工具。

3

我会交易空间的时间,而不是做比较。只需在插入/更新时将新值推送到审计表。磁盘很便宜。

此外,我不确定存储过程购买了什么。你不能做喜欢的事,在触发简单:

insert into dbo.mytable_audit 
    (select *, getdate(), getdate(), 'create' from inserted) 

当扳机上插入运行,要添加创建时间,最后更新时间和修改类型字段。对于更新,这是一个有点tricker因为你需要提供命名参数为创建的时间不应该被更新

insert into dbo.mytable_audit (col1, col2, ...., last_updated, modification) 
    (select *, getdate(), 'update' from inserted) 

而且,你打算只审核成功或失败呢?如果你想审核失败,你会需要触发器以外的东西,因为如果事务回滚,触发器将不会运行 - 而且如果触发器先运行,你将不具有事务的状态。

我实际上已将我的审计移至我的数据访问层,并在代码中执行此操作。它使成功和失败审计变得更容易,并且(使用反射)很容易将字段复制到审计对象。它允许我做的另一件事是给用户上下文,因为我没有给数据库实际的用户权限,并使用服务帐户运行所有查询。

+0

我同意。磁盘很便宜。每次只保存新的(插入的)值。旧值将位于审计表的前一行中。 – MikeW 2009-03-02 23:53:25

1

已经有一个内置函数UPDATE()它告诉你列是否已经改变(但它是在整个插入行集上)。

你可以看看Paul Nielsen's AutoAudit triggers中的一些技术,这些技术是代码生成的。

它能做什么是同时检查:

IF UPDATE(<column_name>) 
INSERT Audit (...) 
SELECT ... 
FROM Inserted 
JOIN Deleted 
    ON Inserted.KeyField = Deleted.KeyField -- (AutoAudit does not support multi-column primary keys, but the technique can be done manually) 
AND NOT (Inserted.<column_name> = Deleted.<column_name> OR COALESCE(Inserted.<column_name>, Deleted.<column_name>) IS NULL) 

但审计每一列的变化作为一个单独的行。我使用它来审计配置表的更改。我目前没有用它来审计繁重的变更表。 (但是在我设计的大多数事务处理系统中,重活动表上的行通常是不可变的,您没有太多的UPDATE s,只是很多INSERT s - 所以您甚至不需要这种审计) 。例如,订单或分类帐条目永远不会改变,购物车是一次性的 - 也不会有这种审计。在像客户这样的低交易量表上,您可以使用这种审计。

1

Jeff, 我同意Zodeus ..一个好的选择是使用第三个工具。 我已经使用审计数据库(免费)网络工具,生成审计触发器(你不需要写一行TSQL代码)

另一个好的工具是Apex SQL审计,但它不是免费的。

我希望这可以帮助你, F.奥尼尔

+0

网站是www.auditdatabase.com – 2009-03-30 04:49:12