Ответы:
Да, можно определить работающий код, используя системную функцию @@ procid , и лучше присвоить OBJECT_NAME (@@ PROCID) полное имя.
Определение: «Возвращает идентификатор объекта (ID) текущего модуля Transact-SQL. Модуль Transact-SQL может быть хранимой процедурой, пользовательской функцией или триггером. @@ PROCID нельзя указывать в модулях CLR или в обработчик доступа к данным. "
Вы можете прочитать об этом здесь .
Другой вариант - проверить план sql текущего spid и сохранить эту информацию в таблице журналов. Пример запроса, который будет использоваться в каждой процедуре для сохранения данных аудита:
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
Может быть, там слишком много деталей .. но я верю, что вы поняли идею.
Третий вариант - использовать информацию context_info для текущего сеанса SP. И связать где-нибудь контекстную информацию, сохраненную там с каждой процедурой. Например, в процедуре1 вы пишете 111 в контекст, в процедуре2 вы пишете 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 предоставляют другой способ получения стека T-SQL, хотя SQL Server 2008 может не поддерживать используемый тип событий. Решение состоит из триггера, ошибки и сеанса XEvent. Я взял пример Джима Брауна, чтобы показать, как он работает.
Прежде всего, я протестировал решение для SQL Server 2016 SP2CU2 Dev Edition. SQL Server 2008 поддерживает некоторые EXevent, но у меня нет ни одного экземпляра, чтобы я не смог его протестировать.
Идея состоит в том, чтобы сгенерировать пользовательскую ошибку в фиктивном блоке try-catch, а затем перехватить ошибку в сеансе XEvent с tsql_stack
действием. SQLSERVER.error_reported
Тип XEvent может перехватывать все ошибки, даже если блок try-catch их перехватывает. В конце sys.dm_exec_sql_text
извлеките запросы T-SQL из дескрипторов запросов, которые tsql_stack
дает действие.
Пример из ответа Джима Брауна, который я разработал, показан ниже. Триггер вызывает ошибку с текстом «поймай меня». Сессия XEvent ловит ошибки только с текстом типа «поймай меня».
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 позволит вам сделать гораздо больше, чем это! Не упустите возможности узнать их!