我正在编写一个触发器来审核表中的更新和删除。我正在使用SQL Server 2008
我的问题是,
有没有办法在不经过已删除和插入表的选择阶段的情况下找出正在对记录执行的操作?
另一个问题是,如果要删除记录,我如何在审计表中记录执行删除的用户。 (注意:连接到数据库的用户是具有设置用户的常规连接字符串,我需要登录到Web应用程序或Windows应用程序的用户)
请帮帮忙?
答案 0 :(得分:4)
考虑到这一点,如果您实际上没有删除记录但添加了一个字段以将其标记为已删除,则可以从上次修改后获取用户。如果您想要实际删除记录,那么您可以让一个夜间作业在批处理中删除,而不是一次删除。如果有太多的记录被删除而没有运行,甚至可以设置为标记。
这样做的最简单方法是不重命名是重命名表,将列IsDeleted添加为位字段,然后创建一个名称与该表名称相同的视图。该视图将选择isdelted为null的所有记录。
不要让任何人告诉你使用触发器。您不希望进行未经授权更改的人员能够逃避审核。使用触发器(除了生产dba之外没有权限以任何方式更改表),除了dba之外没有人可以删除而不进行审计。在没有存储过程限制直接表访问的典型系统中,所有太多人通常可以直接影响打开它以进行欺诈的表。提交欺诈的人通常不会使用他们应该用来更改数据的应用程序。您必须在数据库级别保护数据。
编写触发器时,请确保它们可以处理多行插入/更新/删除。触发器对整个数据集进行操作,而不是一次一行。
答案 1 :(得分:3)
对于第一部分,您可以设置单独的触发器,也可以使用一个触发器来检查特殊表INSERTED
和DELETED
,以区分更新和删除。
对于第二部分,在这种情况下没有办法绕过它,你将不得不通过你的web / windows应用程序以某种方式将数据库用于数据库。遗憾的是,您无法与触发器本身进行通信,并且使用通用连接字符串,数据库不知道它正在处理谁。
我发现将“LastModifiedBy”列添加到您计划审核的表中会很有帮助,这样您就可以将这些信息存储在原始表本身上。然后,您的触发器只会将该信息复制到审计表中。这也很好,因为如果你只需要知道最后一个接触某人的人是谁,你根本不必查看审计表,只需检查一列。
答案 2 :(得分:3)
正如roufamatic所说,您可以设置特定于每个操作的触发器,也可以检查INSERTED和DELETED表。
对于删除用户,只要应用程序中的代码处理它,就可以将该信息传递给触发器。大约一年前,我遇到了一个客户端的这个要求,我想出的解决方案是使用SET CONTEXT_INFO和CONTEXT_INFO()来传递用户名。我们所有的数据库访问都是通过存储过程进行的,所以我只需要在删除存储过程中添加一行或两行代码来SET CONTEXT_INFO然后我更改了删除触发器以从CONTEXT_INFO()中获取用户。当然,用户名必须作为参数从应用程序传递。如果您没有使用存储过程,则可以在应用程序中执行SET CONTEXT_INFO。我不知道连接池可能会如何影响该方法。显然,如果有人在应用程序之外进行删除,则不会有记录,除非您还在触发器中单独捕获了USERNAME()(可能是个好主意,尽管我们的审计日志不是必需的,报告比安全更多。
有一点点棘手,因为CONTEXT_INFO是一个二进制字符串,但它没有花很长时间才能完全解决。
我担心我没有任何代码,因为它是过去的客户端。如果您在完成CONTEXT_INFO和SET CONTEXT_INFO的帮助后遇到任何问题,请随时在此发布,我会看到我能记住的内容。
答案 3 :(得分:1)
要了解正在采取的操作,可以使用INSERTED和DELETED表来比较值之前和之后。没有神奇的方法可以告诉Web应用程序的哪个用户进行了更改。通常的方法是在表中添加一个修改过的列,并使用相关的用户名
填充此Web应用程序代码