0

J'ai processus qui a démarré par une procédure stockée qui passe plusieurs couches profondes. Jusqu'à 12 procédures stockées ultérieures pourraient être impliquées.Audit Trigger avec procédure stockée ID

J'ai une table qui devient une colonne mise à jour de manière incorrecte au cours du processus ci-dessus et je voudrais savoir quelle procédure stockée est celui qui fait la mise à jour erronée.

J'ai examiné l'audit de table via des déclencheurs et j'ai essayé d'utiliser la fonction SCOPE_IDENTITY pour identifier la procédure stockée qui est le coupable mais elle renvoie une valeur NULL à ma table d'audit.

Est-ce que je suis en train de faire possible? J'essaye fondamentalement d'employer ceci au lieu de déboguer avec lequel j'ai eu le succès limité dans le passé, et je préférerais ne pas éditer les procédures stockées afin de capturer l'information.

Voici mon code: J'ai créé une procédure de test stockée pour mettre à jour la table en question.

--Create test Sproc 

    IF EXISTS (SELECT * FROM sys.objects (NOLOCK) WHERE name LIKE 'usp_update_pkd') 
    BEGIN 
     DROP PROCEDURE usp_update_pkd 
    END 
    GO 

    CREATE PROCEDURE usp_update_pkd 
    @p_order_number VARCHAR(30) 

    AS 

    UPDATE t_pick_detail 
    SET status = 'XXX' 
    WHERE order_number = @p_order_number 
    RETURN 
    GO 


    --Create Audit Table 
    IF EXISTS (SELECT * FROM sys.objects (NOLOCK) WHERE name LIKE 't_pkd_audit') 
     BEGIN 
     DROP TABLE t_pkd_audit 
     END 
    GO 
    CREATE TABLE t_pkd_audit 
    (
     order_audit_id INTEGER IDENTITY(1,1) PRIMARY KEY, 
     wave_id  VARCHAR(10), 
     work_type  VARCHAR(20), 
     order_number VARCHAR(20), 
     sproc_id  NVARCHAR(128), 
     updated_on  DATETIME 
    ) 
    GO 

     --Create Trigger 
     IF EXISTS (SELECT * FROM sys.objects (NOLOCK) WHERE name LIKE 'pkd_audit_record') 
    BEGIN 
     DROP TRIGGER pkd_audit_record 
    END 
    GO 

    CREATE TRIGGER pkd_audit_record ON t_pick_detail 
    AFTER UPDATE 
    AS 
    BEGIN 
     INSERT INTO t_pkd_audit 
     (wave_id, work_type, order_number, sproc_id, updated_on) 
     SELECT DISTINCT i.wave_id, i.work_type, i.order_number, CAST(SCOPE_IDENTITY() AS VARCHAR), GETDATE() 
     FROM t_pick_detail t 
     INNER JOIN inserted i 
     ON t.order_number = i.order_number 
     AND t.line_number = i.line_number 
    END 
    GO 

    --Execute test SProc 
    EXEC usp_update_pkd '4045' 

    --Check Results 
    SELECT * FROM t_pkd_audit (NOLOCK) 

--Result Set 
order_audit_id|wave_id|work_type|order_number|sproc_id|updated_on 
1    |NULL |17  |4045  |NULL |2017-06-22 00:47:52.513 

Toute aide est très appréciée.

+0

Avez-vous essayé context_info? https://docs.microsoft.com/en-us/sql/t-sql/functions/context-info-transact-sql – Peter

+0

Salut Peter, d'après ce que j'ai lu, cela m'obligerait à modifier les procédures stockées en question et Définissez la valeur context_info dans leur code source. Est-ce que ma compréhension est correcte? S'il n'y a pas d'autre moyen que le serveur SQL suit implicitement la procédure dans laquelle il se trouve lors de l'exécution de DML, cela peut fonctionner. – dska84

Répondre

0

Ajouter une colonne à votre table d'audit qui contiendra le nom de la procédure stockée. Parce qu'il a une valeur par défaut, vous n'avez pas besoin de modifier votre déclencheur, mais vous pouvez supprimer sproc_id si vous le souhaitez. La valeur par défaut prendra le @@ PROCID stocké dans context_info et l'utilisera pour obtenir le nom de la procédure stockée.

CREATE TABLE t_pkd_audit 
(
    order_audit_id INTEGER IDENTITY(1,1) PRIMARY KEY, 
    wave_id  VARCHAR(10), 
    work_type  VARCHAR(20), 
    order_number VARCHAR(20), 
    sproc_id  NVARCHAR(128), 
    updated_on  DATETIME, 
    SpName [varchar](128) NULL CONSTRAINT [DF_a_hist_sourceName] DEFAULT (object_name(CONVERT([int],CONVERT([varbinary](4),context_info())))) 
) 

Pour chacun de vos 12 procédures stockées, commencer par:

declare @calledBy varbinary(128) = coalesce(Context_info(),0),@proc int 
select @proc = @@PROCID 
set context_info @proc 

Il mettra l'id de la procédure stockée dans CONTEXT_INFO et stocker l'ID de la procédure stockée mère dans une variable.

À la fin de chaque procédure stockée. Si vous utilisez des retours, qu'avant chaque retour, ajoutez le code suivant pour réécrire l'identifiant de la procédure stockée parent dans context_info.

set context_info @calledby 
+0

Merci Peter, après avoir lu votre 1er commentaire, je suis parti et j'ai essayé certaines choses et je suis arrivé à votre réponse. Merci encore pour votre aide. J'ai déclenché le processus de l'application et faible et voici le nom de sproc incriminé dans la table d'audit quand il avait fini! Bug trouvé et réparé! – dska84