2010-01-18 75 views
6

时,这是由ERROR_MESSAGE(),ERROR_PROCEDURE(读跟进的问题 Nested stored procedures containing TRY CATCH ROLLBACK pattern?记录SQL服务器调用堆栈报告错误

在catch块我使用存储过程来报告(再加注)错误),ERROR_LINE()等。正如here所描述的那样,我还有一个检查,以便它可以确定错误是否已经被重新抛出(这发生在嵌套存储过程中,因为错误信息通过每个TRY CATCH块传递)。

我想要直接在'ReportError'中,或者间接地使用我的模式(如第一个问题所述)做记录堆栈跟踪 - 所以当ReportError检测到它正在接收抛出的错误时本身,它会将堆栈的下一个级别附加到错误消息中。这可以帮助我避免出现一些错误消息来自某个小实用程序存储过程的情况,而无需知道是什么称呼它。如果我直接在ReportError中尝试这样做,它会失败,因为rethrown错误报告自己来自ReportError - 只有原始错误是可见的。

ReportError是否有一些方法可以在SQL Server中执行堆栈跟踪,而无需将参数传递给每个存储过程,也无需使用#temp table手动维护这种跟踪?基本上我想要一个ERROR_PROCEDURE()和ERROR_LINE()的递归调用。

+1

我刚刚添加了一篇文章,可能会帮助你。我演示了如何在SQL Server中创建调用堆栈。 http://www.thecodepage.com/post/TIP-A-Call-Stack-in-SQL-Server.aspx – 2010-02-03 02:16:28

+0

@GabrielMcAdams链接到您的文章已损坏。任何你可以更新它或在这里发布解决方案的答案吗? – 2016-09-06 17:46:25

回答

1

好吧,我来补充我们的错误:-)处理回

的ERROR_% ()函数对CATCH块的范围可见。这意味着你可以在每个CATCH块

而且具有嵌套存储的特效使用他们在一个存储过程或函数调用,这是非常有用知道是什么引起的错误,什么是记录错误

... 
END TRY 
BEGIN CATCH 
    IF XACT_STATE() <> 0 AND @starttrancount = 0 
     ROLLBACK TRANSACTION 
    EXEC dbo.MyExceptionHandler @@PROCID, @errmsg OUTPUT; 
    RAISERROR (@errmsg, 16, 1); 
END CATCH 

---with this handler (cut down version of ours) 
CREATE PROCEDURE dbo.MyExceptionHandler 
    @CallerProcID int, 
    @ErrorMessage varchar(2000) OUTPUT 
WITH EXECUTE AS OWNER --may be needed to get around metadata visibility issues of OBJECT_NAME 
AS 
SET NOCOUNT, XACT_ABORT ON; 

BEGIN TRY 
    SET @ErrorMessage = --cutdown 
      CASE 
       WHEN @errproc = @callerproc THEN  --Caller = error generator 
         --build up stuff 

       ELSE --Just append stuff    --Nested error stack 
      END; 

    IF @@TRANCOUNT = 0 
     INSERT dbo.Exception (Who, TheError, WhatBy, LoggedBy) 
     VALUES (ORIGINAL_LOGIN()), RTRIM(ERROR_MESSAGE()), ERROR_PROCEDURE(), OBJECT_NAME(@CallerProcID)); 
END TRY 
BEGIN CATCH 
    --and do what exactly? 
END CATCH 
GO 

这是无论如何基本思想:每个CATCH块都很简单,工作在错误处理程序中继续。例如追加ERROR_NUMBER()如果你想

0

对此的一个有限答案是将OBJECT_NAME(@@ PROCID)传递给ReportError过程 - 当ReportError检测到它正在接收递归错误(自身抛出的错误)时,它可以使用该值并将其附加到它到错误消息,其提供的部分堆栈跟踪(堆栈跟踪不会有除了第一要素行号)