0

我有一個由存儲過程啓動的過程,該存儲過程深入幾層。最多可能涉及12個後續存儲過程。具有存儲過程ID的表審計觸發器

我有越來越在上述過程中錯誤地更新一個列的表,我想找出哪些存儲過程是一個使錯誤更新。

我已經通過觸發器看了看錶的審覈和使用SCOPE_IDENTITY函數來確定哪些存儲過程是罪魁禍首試過,但它返回NULL值到我的審覈表。

是什麼,我試圖做可能嗎?我基本上是試圖用這種方式來代替調試,而這在過去我得到了有限的成功,而且我不想編輯存儲過程來捕獲信息。

這裏是我的代碼:我創建了一個測試存儲過程中的問題,以更新表。

--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 

任何幫助,非常感謝。

+0

你試過CONTEXT_INFO? https://docs.microsoft.com/en-us/sql/t-sql/functions/context-info-transact-sql – Peter

+0

嗨,彼得,從我讀的,這將需要我修改有問題的存儲過程和在其源代碼中設置context_info值。我的理解是否正確?如果沒有其他方式SQL服務器隱式地跟蹤它在執行DML時所處的過程,那麼這可能起作用。 – dska84

回答

0

添加列到你的審計表將包含存儲過程的名稱。因爲它有一個默認值,所以你不需要改變你的觸發器,但是如果你喜歡,你可以刪除sproc_id。默認值將採用存儲在context_info中的@@ PROCID並使用它來獲取存儲過程名稱。

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())))) 
) 

對於您的每12個存儲過程,先從:

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

它將把在CONTEXT_INFO存儲過程的ID和存儲父存儲過程的ID在一個變量。

在每個存儲過程結束時。如果您使用了返回,那麼在每個返回之前添加以下代碼以將context存儲過程的id寫回到context_info中。

set context_info @calledby 
+0

感謝彼得,在閱讀你的第一條評論後,我走開了,試了一些東西,基本上已經到達你提交的答案。再次感謝你的幫助。我從應用程序觸發了這個進程並且低了,並且在完成時注意到審計表中存在有問題的sproc名字!找到並修復了Bug! – dska84