【问题标题】:Recording SQL Server call stack when reporting errors报告错误时记录 SQL Server 调用堆栈
【发布时间】:2010-01-18 15:18:11
【问题描述】:

这是对问题的跟进 Nested stored procedures containing TRY CATCH ROLLBACK pattern?

在 catch 块中,我使用存储过程通过读取 ERROR_MESSAGE()、ERROR_PROCEDURE()、ERROR_LINE() 等来报告(重新引发)错误。如 here 所述,我也有一个检查,以便它可以确定错误是否已经被重新抛出(这发生在嵌套存储过程中,因为错误信息通过每个 TRY CATCH 块向下传递)。

我想做的,无论是直接在“ReportError”中,还是间接地使用我的模式(如第一个问题中所述),都是记录堆栈跟踪 - 所以当 ReportError 检测到它正在接收自己抛出的错误时,它将堆栈的下一级附加到错误消息中。这将帮助我避免看到来自一些小实用程序存储过程的错误消息,而无法知道调用它的方法。如果我尝试直接在 ReportError 中执行此操作,它会失败,因为重新抛出的错误报告自己来自 ReportError - 只有原始错误可见。

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

【问题讨论】:

  • 我刚刚在我的博客中添加了一篇可能对您有所帮助的帖子。我将展示如何在 SQL Server 中创建调用堆栈。 thecodepage.com/post/TIP-A-Call-Stack-in-SQL-Server.aspx
  • @GabrielMcAdams 您文章的链接已损坏。您是否有机会在此处更新它或将解决方案作为答案发布?

标签: sql-server-2005 tsql error-handling try-catch stack-trace


【解决方案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()

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2022-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多