我继承了一个 SQL Server 2008 数据库,调用应用程序可以通过存储过程访问该数据库。
数据库中的每个表都有一个影子审计表,其中记录了插入/更新/删除操作。
填充审计表的性能测试表明,使用插入审计记录OUTPUT
子句比使用触发器快 20% 左右,因此这已在存储过程中实现。
但是,由于此设计无法跟踪通过直接针对表发出的 DML 语句直接对表所做的更改,因此还实现了使用以下值的触发器:@@NESTLEVEL
确定是否运行触发器(假设所有通过存储过程运行的 DML 都会有@@NESTLEVEL
> 1).
即触发代码的主体如下所示:
IF @@NESTLEVEL = 1 -- implies call is direct sql so generate history from here
BEGIN
... insert into audit table
这种设计是有缺陷的,因为它不会跟踪动态 SQL 中执行 DML 语句的更新,或者任何其他上下文中的更新。@@NESTLEVEL
被提高到 1 以上。
任何人都可以建议一个完全可靠的方法,我们可以在触发器中使用它来执行它们(仅当不是由存储过程触发时)?
或者这是不可能的(正如我怀疑的那样)?
Use CONTEXT_INFO (Transact-SQL) http://msdn.microsoft.com/en-us/library/ms180125.aspx。在该过程中设置一个值以警告触发器不记录任何内容:
--in the procedure doing the insert/update/delete
DECLARE @CONTEXT_INFO varbinary(128)
SET @CONTEXT_INFO =cast('SkipTrigger=Y'+REPLICATE(' ',128) as varbinary(128))
SET CONTEXT_INFO @CONTEXT_INFO
--do insert/update/delete that will fire the trigger
SET CONTEXT_INFO 0x0
在触发器中检查 CONTEXT_INFO 并确定是否需要执行任何操作:
--here is the portion of the trigger to retrieve the value:
IF CAST(CONTEXT_INFO() AS VARCHAR(128))='SkipTrigger=Y'
BEGIN
--log your data here
END
对于任何只是进行恶意插入/更新/删除的人来说,他们不会设置 CONTEXT_INFO 并且触发器将记录更改。如果您认为恶意代码也会尝试使用 CONTEXT_INFO,那么您可能会喜欢放入 CONTEXT_INFO 中的值,例如表名或 @@SPID 等。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)