gar*_*rik 18 trigger sql-server-2008
我有 10 个存储过程,每个存储过程都将 INSERT 插入到一个 tableX 中。
是否可以在 tableX 的触发器主体中获取导致 tableX 修改的对象(存储的 proc1 或 sp2 或....)?
谢谢你。
Mar*_*ian 10
是的,可以通过使用@@procid 系统函数和更好的 OBJECT_NAME(@@PROCID) 来识别正在运行的代码,以获得完整的名称。
定义:“返回当前 Transact-SQL 模块的对象标识符 (ID)。Transact-SQL 模块可以是存储过程、用户定义函数或触发器。@@PROCID 不能在 CLR 模块中指定,也不能在过程数据访问提供程序。”
你可以在这里阅读它。
另一种选择是检查当前 spid 的 sql 计划并将该信息保存在日志记录表中。在每个过程中用于保存审计数据的示例查询是:
select sp.hostname, sp.program_name, sp.loginame,
st.text as query_text
from sysprocesses sp
cross apply sys.dm_exec_sql_text(sp.sql_handle) as st
where sp.spid = @@spid
Run Code Online (Sandbox Code Playgroud)
也许那里有太多细节......但我相信你明白了。
第三种选择是将context_info信息用于当前 SP 的会话。并将保存在那里的上下文信息与每个过程相关联。例如,在程序 1 中,您将 111 写入上下文,在程序 2 中,您将写入 222.. 等等。
您可以在此 SO question 中阅读有关 context_info 的更多信息。
XEvents 提供了另一种了解 T-SQL 堆栈的方法,尽管 SQL Server 2008 可能不支持所使用的事件类型。该解决方案由触发器、错误和 XEvent 会话组成。我以吉姆·布朗的例子来展示它的工作原理。
\n\n首先,我测试了SQL Server 2016 SP2CU2 Dev Edition的解决方案。SQL Server 2008支持一些EXevent,但我没有任何实例,因此无法测试它。
\n\n这个想法是在虚拟的 try-catch 块中生成用户错误,然后通过操作捕获 XEvent 会话中的错误tsql_stack
。SQLSERVER.error_reported
XEvent 类型可以捕获所有错误,即使 try-catch 块捕获了这些错误。最后,sys.dm_exec_sql_text
从操作给出的查询句柄中提取 T-SQL 查询tsql_stack
。
我开发的吉姆·布朗答案中的一个例子如下所示。触发器会引发带有文本“catch me”的错误。XEvent 会话仅捕获诸如“catch me”之类的文本的错误。
\n\nCREATE TABLE Test ( TestID INT )\n\nGO\n\nCREATE TRIGGER TestTrigger ON Test\nFOR INSERT\nAS\nBEGIN TRY\n SET XACT_ABORT OFF; -- REALLY IMPORTANT!\n /* make an catching a great deal more interesting */\n DECLARE @TestID NVARCHAR(MAX) ;\n SELECT TOP (1) @TestID = CAST(ins.TestID AS NVARCHAR(MAX)) FROM inserted AS ins ;\n RAISERROR (N\'catch_me TestID = "%s"\' , 11 , 0 , @TestID) ;\nEND TRY BEGIN CATCH /* NOTHING TO DO */ END CATCH\n\nGO\n\nCREATE PROCEDURE usp_ProcIDTest\nAS\nINSERT INTO Test ( TestID ) VALUES ( 1 ) \n\nGO\n\nCREATE PROCEDURE usp_RootProcIDTest\nAS\nEXEC usp_ProcIDTest\n\nGO\n\n-- This XEvent session definition was kindly provided by XEvent \'New Session\' wizard.\nCREATE EVENT SESSION [catch_insertion_into_Test] ON SERVER \nADD EVENT sqlserver.error_reported(\n ACTION(package0.callstack,sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.database_id,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.server_principal_name,sqlserver.session_id,sqlserver.session_nt_username,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack,sqlserver.username,sqlserver.context_info,sqlserver.plan_handle)\n WHERE ([message] like N\'catch_me%\'))\nADD TARGET package0.ring_buffer(SET max_memory=(10240))\nWITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=OFF,STARTUP_STATE=ON)\n\nGO\n
Run Code Online (Sandbox Code Playgroud)\n\n现在,如果您启动 XEvent 会话(SSMS、对象资源管理器、管理、扩展事件、会话、catch_insertion_into_Test),执行 usp_RootProcIDTest 并查看 XEvent 会话的环形缓冲区,您应该看到包含节点的 XML <action name="tsql_stack" package="sqlserver">
。存在一系列框架节点。将a的属性值handle
放入系统函数“sys.dm_exec_sql_text”中,然后查看\xc3\xa0:
-- REPLACE MY HANDLES WITH YOURS\nSELECT * FROM sys.dm_exec_sql_text(0x03000800D153096910272C01A6AA000000000000000000000000000000000000000000000000000000000000);\nSELECT * FROM sys.dm_exec_sql_text(0x030008000A78FD6912272C01A6AA000001000000000000000000000000000000000000000000000000000000);\nSELECT * FROM sys.dm_exec_sql_text(0x03000800439CF16A13272C01A6AA000001000000000000000000000000000000000000000000000000000000);\n
Run Code Online (Sandbox Code Playgroud)\n\n\n\nXEvent 让您做的远不止这些!不要错过学习它们的机会!
\n