Question

J'ai 10 procédures stockées et chacun d'eux en un seul ne INSERTs TABLEx.

Est-il possible dans un corps de déclenchement de TABLEx pour obtenir ce que l'objet provoque une modification de TABLEx (stockées PROC1 ou sp2 ou ....)?

Merci.

Était-ce utile?

La solution

Oui, il est possible d'identifier le code en cours d'exécution, par en utilisant la fonction @@ système procid , et mieux OBJECT_NAME (@@ PROCID) pour avoir le nom complet.

Définition:.. « Renvoie l'identificateur d'objet (ID) du module Transact-SQL en cours Module Transact-SQL peut être une procédure stockée, fonction définie par l'utilisateur, ou un déclencheur @@ PROCID ne peut pas être spécifié dans les modules CLR ou le processus en fournisseur d'accès aux données. "

Vous pouvez lire à ce sujet .

Une autre option serait de vérifier le plan sql de la SPID actuelle et enregistrer cette information dans une table de journalisation. Un exemple de requête à utiliser dans chaque procédure pour enregistrer les données d'audit serait:

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

Peut-être il y a trop de détails there..but Je crois que vous avez l'idée.

Une troisième option serait de CONTEXT_INFO informations à la session de la SP en cours. Et quelque part associé les informations de contexte, enregistré avec chaque procédure. Par exemple, dans procédure1 vous écrivez 111 au contexte, dans procédure2 vous écrivez 222 .. et ainsi de suite.

Beaucoup plus d'information concernant CONTEXT_INFO vous pouvez lire dans cette question SO .

Autres conseils

Je voulais faire cela aussi. Merci d'avoir répondu. Comme je suis toujours là, je posterai mon test pour gagner du temps d'autres:)

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 fournissent une autre façon de se faire connaître une pile T-SQL, bien que SQL Server 2008 pourrait ne pas supporter un type d'événement utilisé. La solution se compose d'un déclencheur, une erreur et une session de XEvent. Je pris l'exemple de Jim Brown pour montrer la façon dont il fonctionne.

Tout d'abord, j'ai testé la solution pour SQL Server 2016 SP2CU2 Dev Edition. SQL Server 2008 prend en charge certains EXevent, mais je n'ont pas exemple pour que je ne pouvais pas le tester.

L'idée est de générer une erreur de l'utilisateur dans un bloc try-catch factice, puis attraper l'erreur dans une session XEvent avec l'action tsql_stack. le type SQLSERVER.error_reported XEvent peut attraper toutes les erreurs, même si un bloc try-catch les pièges. En fin de compte, extrait de sys.dm_exec_sql_text requêtes T-SQL des poignées de requête action qui donne tsql_stack.

Un exemple de la réponse de Jim Brown, que j'ai développé, est illustré ci-dessous. Un déclencheur déclenche l'erreur avec le texte « me attraper ». Les erreurs de prises de session XEvent uniquement avec le texte comme « me attraper ».

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

Maintenant, si vous lancez la session XEvent (SSMS, l'Explorateur d'objets, gestion, événements étendus, Sessions, catch_insertion_into_Test), exécuter usp_RootProcIDTest et regardez le tampon circulaire de la session de XEvent, vous devriez voir le XML qui consiste le nœud <action name="tsql_stack" package="sqlserver">. Il y a une séquence de noeuds de trame. Mettez les valeurs d'un attribut de handle dans la fonction système « sys.dm_exec_sql_text », et le tour est joué:

-- 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 vous laisse faire beaucoup plus que cela! Ne manquez pas l'occasion de les apprendre!

Licencié sous: CC-BY-SA avec attribution
Non affilié à dba.stackexchange
scroll top