4

我正在编写一个触发器来审核表中的更新和删除。我正在使用 SQL Server 2008

我的问题是,

有没有办法在不经过删除和插入表的选择阶段的情况下找出对记录采取的操作?

另一个问题是,如果正在删除记录,我如何在审计表中记录正在执行删除的用户。(注意:连接到数据库的用户是具有设置用户的通用连接字符串,我需要登录到 Web 应用程序或 Windows 应用程序的用户)

请帮忙?

4

4 回答 4

4

考虑到这一点,如果您实际上并没有删除记录,而是添加了一个字段以将它们标记为已删除,您可以从上次修改中获取用户。如果你想实际删除记录,你可以有一个夜间作业,批量删除,而不是一次删除。如果有太多记录被删除并且没有运行,这甚至可以设置为标记。

这样做的最简单的方法是重命名表,将列 IsDeleted 添加为位字段,然后创建一个与最初调用表的名称相同的视图。该视图将选择所有 isdelted 为空的记录。

不要让任何人劝你不要为此使用触发器。您不希望进行未经授权的更改的人能够逃脱审核。使用触发器(并且除了生产 dba 之外的任何人都无权以任何方式更改表),那么除了 dba 之外没有人可以在未经审计的情况下删除。在一个没有存储过程来限制直接表访问的典型系统中,太多的人通常会直接影响一个表打开它以进行欺诈。进行欺诈的人通常不会使用他们应该用来更改数据的应用程序。您必须在数据库级别保护数据。

当您编写触发器时,请确保它们可以处理多行插入/更新/删除。触发器对整个数据集进行操作,而不是一次一行。

于 2010-06-08T19:22:48.713 回答
4

对于第一部分,您可以设置单独的触发器,也可以使用一个触发器来检查特殊表INSERTEDDELETED区分更新和删除。

对于第二部分,在这种情况下没有办法解决,您将不得不通过您的 web/windows 应用程序以某种方式将该用户名获取到数据库。不幸的是,您无法与触发器本身进行通信,并且使用通用连接字符串,数据库不知道它正在与谁打交道。

我发现将“LastModifiedBy”列添加到您计划审核的表中会很有帮助,这样您就可以将该信息存储在原始表本身上。然后你的触发器只是将该信息复制到审计表中。这也很好,因为如果您只需要知道最后一个触摸某物的人是谁,您根本不需要查看审计表,只需检查一列。

于 2010-06-08T17:31:48.813 回答
3

正如 roufamatic 所说,您可以设置特定于每个操作的触发器,也可以检查 INSERTED 和 DELETED 表。

至于删除用户,只要您的应用程序中的代码处理它,就可以将该信息传递到触发器中。大约一年前,我和一个客户遇到了这个要求,我想出的解决方案是使用 SET CONTEXT_INFO 和 CONTEXT_INFO() 来传递用户名。我们所有的数据库访问都是通过存储过程进行的,所以我只需要在删除存储过程中添加一两行代码到 SET CONTEXT_INFO 然后我更改删除触发器以从 CONTEXT_INFO() 获取用户。当然,用户名必须作为参数从应用程序中传递。如果您不使用存储过程,则可以只在应用程序中执行 SET CONTEXT_INFO。我不知道连接池如何影响该方法。明显地,

因为 CONTEXT_INFO 是一个二进制字符串,所以有点棘手,但很快就解决了所有问题。

恐怕我手头没有任何代码,因为它是给过去的客户的。如果您在通过 CONTEXT_INFO 和 SET CONTEXT_INFO 的帮助后遇到任何问题,请随时在此处发布,我会看看我能记住什么。

于 2010-06-08T17:47:00.910 回答
1

要找出正在采取的操作,您可以使用 INSERTED 和 DELETED 表来比较前后值。没有什么神奇的方法可以告诉 Web 应用程序的哪个用户进行了更改。通常的方法是在表中修改列,并使用相关的用户名填充 Web 应用程序代码

于 2010-06-08T17:31:20.657 回答