Respuestas:
Sí, es posible identificar el código en ejecución, utilizando la función de sistema @@ procid , y mejor OBJECT_NAME (@@ PROCID) para tener el nombre completo.
Definición: "Devuelve el identificador de objeto (ID) del módulo Transact-SQL actual. Un módulo Transact-SQL puede ser un procedimiento almacenado, una función definida por el usuario o un disparador. @@ PROCID no se puede especificar en los módulos CLR o en el proveedor de acceso a datos de proceso ".
Puedes leer sobre esto aquí .
Otra opción sería verificar el plan sql del spid actual y guardar esa información en una tabla de registro. Una consulta de muestra que se utilizará en cada procedimiento para guardar datos de auditoría sería:
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
Tal vez hay demasiados detalles allí ... pero creo que entiendes la idea.
Una tercera opción sería utilizar la información context_info para la sesión del SP actual. Y asocie en algún lugar la información de contexto guardada allí con cada procedimiento. Por ejemplo, en el procedimiento 1, escribe 111 en el contexto, en el procedimiento 2, escribe 222 ... y así sucesivamente.
Puede leer mucha más información sobre context_info en esta pregunta SO .
OBJECT_NAME(@@PROCID)
devuelve el nombre del disparador, no el proceso de llamada.
Yo también quería hacer esto. Gracias por la respuesta. Como todavía estoy aquí, publicaré mi prueba para ahorrar tiempo a otros :)
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 proporciona otra forma de dar a conocer una pila T-SQL aunque SQL Server 2008 podría no admitir un tipo de evento usado. La solución consiste en un disparador, un error y una sesión XEvent. Tomé el ejemplo de Jim Brown para mostrar cómo funciona.
En primer lugar, probé la solución para SQL Server 2016 SP2CU2 Dev Edition. SQL Server 2008 admite algunos EXevent, pero no tengo ninguna instancia, por lo que no pude probarlo.
La idea es generar un error de usuario en un bloque ficticio try-catch, luego detectar el error dentro de una sesión XEvent con tsql_stack
acción. SQLSERVER.error_reported
El tipo XEvent puede detectar todos los errores aunque un bloque try-catch los atrape. Al final, sys.dm_exec_sql_text
extraiga las consultas T-SQL de los controles de consulta que tsql_stack
da la acción.
A continuación se muestra un ejemplo de la respuesta de Jim Brown, que desarrollé. Un disparador genera el error con el texto 'atraparme'. La sesión de XEvent detecta errores solo con el texto como "Atrápame".
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
Ahora, si inicia la sesión XEvent (SSMS, Object Explorer, Management, Extended Events, Sessions, catch_insertion_into_Test), ejecute usp_RootProcIDTest y mire el búfer en anillo de la sesión XEvent, debería ver el XML que consiste en el nodo <action name="tsql_stack" package="sqlserver">
. Hay una secuencia de nodos de trama. Ponga los valores de un handle
atributo 's en la función del sistema' sys.dm_exec_sql_text ', y 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 te permite hacer mucho más que esto! ¡No pierdas las oportunidades de aprenderlas!