回答:
はい、@@ procidシステム関数を使用して実行中のコードを識別し、完全な名前を付けるためにOBJECT_NAME(@@ PROCID)を使用できます。
定義:「現在のTransact-SQLモジュールのオブジェクト識別子(ID)を返します。Transact-SQLモジュールは、ストアドプロシージャ、ユーザー定義関数、またはトリガーになります。@@ PROCIDはCLRモジュールまたはin-プロセスデータアクセスプロバイダー。」
別のオプションは、現在の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
そこには詳細が多すぎるかもしれません。しかし、私はあなたがアイデアを得ると信じています。
3番目のオプションは、context_info情報を現在のSPのセッションに使用することです。そして、そこに保存されたコンテキスト情報を各手順に関連付けます。たとえば、procedure1では111をコンテキストに書き込み、procedure2では222 ..を書き込みます。
context_infoに関する詳細情報は、このSOの質問で読むことができます。
OBJECT_NAME(@@PROCID)
では、呼び出し側のプロシージャではなくトリガー名が返されます。
私もこれをやりたかった。答えてくれてありがとう。私はまだここにいるので、他の人の時間を節約するためにテストを投稿します:)
CREATE TABLE Test ( TestID INT )
GO
CREATE TRIGGER TestTrigger ON Test
FOR INSERT
AS
SELECT CAST(CONTEXT_INFO() AS NVARCHAR(128));
GO
CREATE PROCEDURE usp_ProcIDTest
AS
DECLARE @ProcedureName VARBINARY(MAX) = CAST(OBJECT_NAME(@@PROCID) AS VARBINARY(MAX))
SET CONTEXT_INFO @ProcedureName
INSERT INTO Test ( TestID ) VALUES ( 1 )
GO
EXEC usp_ProcIDTest
GO
DROP TABLE Test
GO
XEventsは、SQL Server 2008が使用されたイベントタイプをサポートしていない場合でも、T-SQLスタックを知るための別の方法を提供します。ソリューションは、トリガー、エラー、およびXEventセッションで構成されます。私はジム・ブラウンの例を取り上げて、その仕組みを示しました。
まず、SQL Server 2016 SP2CU2 Dev Editionのソリューションをテストしました。SQL Server 2008はいくつかのEXeventをサポートしますが、テストできないようにインスタンスがありません。
アイデアは、ダミーのtry-catchブロックでユーザーエラーを生成し、tsql_stack
アクションを使用してXEventセッション内でエラーをキャッチすることです。SQLSERVER.error_reported
XEventタイプは、try-catchブロックがエラーをトラップしても、すべてのエラーをキャッチできます。最後に、アクションが与えるsys.dm_exec_sql_text
クエリハンドルからT-SQLクエリを抽出しますtsql_stack
。
私が開発したジムブラウンの回答の例を以下に示します。トリガーは、テキスト「catch me」でエラーを発生させます。XEventセッションは、「catch me」などのテキストでのみエラーをキャッチします。
CREATE TABLE Test ( TestID INT )
GO
CREATE TRIGGER TestTrigger ON Test
FOR INSERT
AS
BEGIN TRY
SET XACT_ABORT OFF; -- REALLY IMPORTANT!
/* make an catching a great deal more interesting */
DECLARE @TestID NVARCHAR(MAX) ;
SELECT TOP (1) @TestID = CAST(ins.TestID AS NVARCHAR(MAX)) FROM inserted AS ins ;
RAISERROR (N'catch_me TestID = "%s"' , 11 , 0 , @TestID) ;
END TRY BEGIN CATCH /* NOTHING TO DO */ END CATCH
GO
CREATE PROCEDURE usp_ProcIDTest
AS
INSERT INTO Test ( TestID ) VALUES ( 1 )
GO
CREATE PROCEDURE usp_RootProcIDTest
AS
EXEC usp_ProcIDTest
GO
-- This XEvent session definition was kindly provided by XEvent 'New Session' wizard.
CREATE EVENT SESSION [catch_insertion_into_Test] ON SERVER
ADD EVENT sqlserver.error_reported(
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)
WHERE ([message] like N'catch_me%'))
ADD TARGET package0.ring_buffer(SET max_memory=(10240))
WITH (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)
GO
ここで、XEventセッション(SSMS、オブジェクトエクスプローラー、管理、拡張イベント、セッション、catch_insertion_into_Test)を起動し、usp_RootProcIDTestを実行してXEventセッションのリングバッファーを調べると、ノードを構成するXMLが表示されます<action name="tsql_stack" package="sqlserver">
。一連のフレームノードがあります。handle
の属性の値をシステム関数「sys.dm_exec_sql_text」に入れてください。
-- REPLACE MY HANDLES WITH YOURS
SELECT * FROM sys.dm_exec_sql_text(0x03000800D153096910272C01A6AA000000000000000000000000000000000000000000000000000000000000);
SELECT * FROM sys.dm_exec_sql_text(0x030008000A78FD6912272C01A6AA000001000000000000000000000000000000000000000000000000000000);
SELECT * FROM sys.dm_exec_sql_text(0x03000800439CF16A13272C01A6AA000001000000000000000000000000000000000000000000000000000000);
XEventを使用すると、これ以上のことができます。それらを学ぶ機会をお見逃しなく!