トリガーで実行コールスタックを取得することは可能ですか?
-
16-10-2019 - |
質問
私は10個のストアドプロシージャを持っています、そして、それらはそれぞれ1つのtablexに挿入します。
Tablexのトリガー本文で、Tablex(保存されたProc1またはSp2または....)の変更を引き起こすオブジェクトを取得することは可能ですか?
ありがとうございました。
解決
はい、実行中のコードを識別することが可能です @@ procidシステム関数を使用します, 、およびより良いObject_name(@@ procid)は完全な名前を持っています。
定義:「現在のTransact-SQLモジュールのオブジェクト識別子(ID)を返します。Transact-SQLモジュールは、ストアドプロシージャ、ユーザー定義関数、またはトリガーになります。データアクセスプロバイダーを処理します。」
あなたはそれについて読むことができます ここ.
別のオプションはそうです 現在の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のセッションに。コンテキスト情報が各手順で保存されたどこかで関連付けます。たとえば、手順1では、コンテキストに111を書き込み、手順2で222を書き込みます。
あなたが読むことができるContext_infoに関する多くの情報 これはとても質問です.
他のヒント
私もこれをやりたかった。答えをありがとう。私はまだここにいるので、私は他の時間を節約するために私のテストを投稿します:)
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エディションのソリューションをテストしました。 SQL Server 2008はいくつかのExeventをサポートしていますが、テストできないため、インスタンスはありません。
アイデアは、ダミートライキャッチブロックでユーザーエラーを生成し、Xeventセッション内でエラーをキャッチすることです。 tsql_stack
アクション。 SQLSERVER.error_reported
Xeventタイプは、トライキャッチブロックがそれらをトラップしても、すべてのエラーをキャッチできます。最終的には、 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">
. 。フレームノードのシーケンスがあります。 aの値を置きます handle
システム関数への属性 'sys.dm_exec_sql_text'、およびvoilà:
-- 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はこれ以上のことをさせてください!それらを学ぶ機会をお見逃しなく!