Risposte:
Sì, è possibile identificare il codice in esecuzione, utilizzando la funzione di sistema @@ procid e OBJECT_NAME migliore (@@ PROCID) per avere il nome completo.
Definizione: "Restituisce l'identificatore di oggetto (ID) dell'attuale modulo Transact-SQL. Un modulo Transact-SQL può essere una procedura memorizzata, una funzione definita dall'utente o un trigger. @@ PROCID non può essere specificato nei moduli CLR o in fornitore di accesso ai dati di processo ".
Puoi leggerlo qui .
Un'altra opzione sarebbe quella di controllare il piano sql dello spid corrente e salvare tali informazioni in una tabella di registrazione. Una query di esempio da utilizzare in ciascuna procedura per salvare i dati di controllo sarebbe:
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
Forse ci sono troppi dettagli lì..ma credo che tu abbia avuto l'idea.
Una terza opzione sarebbe quella di utilizzare le informazioni context_info per la sessione del SP corrente. E associare da qualche parte le informazioni di contesto salvate lì con ogni procedura. Ad esempio nella procedura1 si scrive 111 nel contesto, nella procedura2 si scrive 222 .. e così via.
Molte altre informazioni su context_info sono disponibili in questa domanda SO .
OBJECT_NAME(@@PROCID)
restituisce il nome del trigger, non il proc chiamante.
Volevo fare anche questo. Grazie per la risposta. Dato che sono ancora qui, posterò il mio test per risparmiare tempo agli altri :)
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 offre un altro modo per far conoscere uno stack T-SQL sebbene SQL Server 2008 potrebbe non supportare un tipo di evento utilizzato. La soluzione consiste in un trigger, un errore e una sessione XEvent. Ho preso l'esempio di Jim Brown per mostrare come funziona.
Prima di tutto, ho testato la soluzione per SQL Server 2016 SP2CU2 Dev Edition. SQL Server 2008 supporta alcuni EXevent, ma non ho alcuna istanza in modo da non poterlo testare.
L'idea è di generare un errore utente in un fittizio blocco try-catch, quindi rilevare l'errore all'interno di una sessione XEvent con tsql_stack
azione. SQLSERVER.error_reported
Il tipo XEvent può rilevare tutti gli errori anche se un blocco try-catch li intercetta. Alla fine, sys.dm_exec_sql_text
estrarre le query T-SQL dagli handle di query che tsql_stack
azione fornisce.
Un esempio della risposta di Jim Brown, che ho sviluppato, è mostrato di seguito. Un trigger genera l'errore con il testo "catch me". La sessione XEvent rileva errori solo con il testo come "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
Ora, se avvii la sessione XEvent (SSMS, Esplora oggetti, Gestione, Eventi estesi, Sessioni, catch_insertion_into_Test), esegui usp_RootProcIDTest e guardi il buffer dell'anello della sessione XEvent, dovresti vedere l'XML che costituisce il nodo <action name="tsql_stack" package="sqlserver">
. Esiste una sequenza di nodi di frame. Inserisci i valori dell'attributo handle
's nella funzione di sistema' sys.dm_exec_sql_text 'e 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 ti consente di fare molto di più! Non perdere le occasioni per impararli!