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