【问题标题】:Is it possible for a trigger to find the name of the stored procedure that modified data?触发器是否可以找到修改数据的存储过程的名称?
【发布时间】:2010-11-23 21:45:00
【问题描述】:

有一些存储过程通常会被几个不同的系统调用以对我们数据库中的一些表进行维护。有些是自动化的,有些不是。

其中一个表格有一列数字有时会关闭,我们不确定何时或为什么会发生这种情况。我想在表格上放置一个触发器,这样我就可以看到正在更改的内容和时间,但了解哪个过程启动了修改也会很有帮助。

是否可以从触发器中获取存储过程的名称?如果没有,有没有其他方法可以说明是什么导致了某些内容被修改? (我也不是在谈论用户,在这种情况下用户的名字没有帮助)。

【问题讨论】:

  • 我认为这不可能,因为它可能不是运行的存储过程,它可能是一个简单的批处理。我可能错了,但我想说,在你的情况下,你应该研究某种方法来获取涉及特定表的最近批次的列表,这基本上就是监视器的作用。

标签: sql-server-2005 stored-procedures triggers


【解决方案1】:

你可以试试:CONTEXT_INFO

这是一个 CONTEXT_INFO 用法示例:

在执行您要跟踪的插入/删除/更新的每个过程中,添加以下内容:

DECLARE @string        varchar(128)
       ,@CONTEXT_INFO  varbinary(128)
SET @string=ISNULL(OBJECT_NAME(@@PROCID),'none')
SET @CONTEXT_INFO =cast('Procedure='+@string+REPLICATE(' ',128) as varbinary(128))
SET CONTEXT_INFO @CONTEXT_INFO

--do insert/delete/update that will fire the trigger

SET CONTEXT_INFO 0x0 --clears out the CONTEXT_INFO value

这里是获取值的触发器部分:

DECLARE @string         varchar(128)
       ,@sCONTEXT_INFO  varchar(128)
SELECT @sCONTEXT_INFO=CAST(CONTEXT_INFO() AS VARCHAR) FROM master.dbo.SYSPROCESSES WHERE SPID=@@SPID

IF LEFT(@sCONTEXT_INFO,9)='Procedure'
BEGIN
    SET @string=RIGHT(RTRIM(@sCONTEXT_INFO),LEN(RTRIM(@sCONTEXT_INFO))-10)
END
ELSE
BEGIN --optional failure code
    RAISERROR('string was not specified',16,1)
    ROLLBACK TRAN
    RETURN
END

..use the @string

【讨论】:

  • @KM,谢谢,我会试一试,但我不确定我的团队是否会对我完成并修改每个存储过程以进行临时调试感到兴奋:P
  • 如果不修复这个错误会更兴奋吗?触发器有时会很痛苦。
  • APP_NAME() 有助于跟踪不同的系统。
【解决方案2】:

我们的系统已将 CONTEXT_INFO 变量用于其他目的,因此该变量不可用。我还尝试了几乎可以工作的DBCC INPUTBUFFER solution。输入缓冲区的缺点是它只返回外部调用过程。例如:procA 调用触发触发器的 procB。触发器运行仅显示 procA 的 DBCC INPUTBUFFER。由于我的触发器正在寻找 procB,因此这种方法失败了。

我在此期间所做的是创建一个临时表。现在 procA 调用 procB。 procB 在临时表中插入一行,然后触发触发器。触发器检查登台表并找到 procB 条目。返回时,procB 从登台表中删除其条目。这是一个空壳游戏,但它有效。我会对此感兴趣的任何反馈。

【讨论】:

  • 遗憾的是,这是解决 SQL Server 中严重缺乏任何过程/触发器调用堆栈的最佳解决方法。甚至甲骨文都有这个!我工作的第 3 方数据库也到处使用CONTEXT_INFO。我现在可以提供的唯一新建议是使用 SS2016,您可以使用 MEMORY_OPTIMIZED 表将临时调用堆栈信息存储在内存中,或使用 SESSION_CONTEXT 跟踪 ONLY 最近的 @987654325 @ 热土豆。注意:从 SS2014-SP2 开始,您还可以使用 sys.dm_exec_input_buffer() 而不声明表变量并调用动态 SQL 来执行 DBCC INPUTBUFFER。
【解决方案3】:

我没有尝试过,但@@PROCID 看起来可能会返回你想要的。

【讨论】:

  • 我相信一旦你进入了触发器代码,这将返回触发器本身的 ID。
  • 正确。 @@procid(或 object_name(@@procid))可用作表中的列默认值,以了解插入的来源。
猜你喜欢
  • 1970-01-01
  • 2020-05-20
  • 1970-01-01
  • 1970-01-01
  • 2019-04-09
  • 2017-01-17
  • 2018-09-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多