如何在 SQL 代理中公开有关存储过程失败的更多信息

发布于 2024-10-21 05:15:48 字数 432 浏览 4 评论 0原文

我有一个 SQL 代理作业设置,在该作业中有一个执行存储过程的步骤。如果该存储过程失败,则 SQL 代理作业将显示一条错误消息,但没有其他信息。像堆栈跟踪或至少正在运行的存储过程和行号之类的东西将非常有用。

例如 如果执行以下存储过程,则会出现错误消息,例如“以用户身份执行:NT AUTHORITY\NETWORK SERVICE。启动[SQLSTATE 01000](消息0)无效的对象名称'NonExistentTable'。[SQLSTATE 42S02](错误208)。该步骤失败的。”没有任何迹象表明故障具体发生在哪里。

CREATE PROCEDURE TestSpLogging AS 
BEGIN
PRINT 'Start'
SELECT * FROM NonExistentTable
PRINT 'End'
END

公开此信息的最佳方式是什么?

I have a SQL agent job setup and in that job there is a step to execute a stored proc. If that stored proc fails then the SQL agent job will display an error message but there is no other information. Something like a stacktrace or at least the stored proc that was running and the line number would be highly useful.

e.g.
If the following stored proc is executed then an error message like "Executed as user: NT AUTHORITY\NETWORK SERVICE. Start [SQLSTATE 01000] (Message 0) Invalid object name 'NonExistentTable'. [SQLSTATE 42S02] (Error 208). The step failed." with no indication where exactly the failure occured.

CREATE PROCEDURE TestSpLogging AS 
BEGIN
PRINT 'Start'
SELECT * FROM NonExistentTable
PRINT 'End'
END

What's the best way to expose this information?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦里梦着梦中梦 2024-10-28 05:15:49

使用 http://www.sommarskog.se/error_handling_2005.html 中详细介绍的方法似乎到目前为止工作足够。它只需要更新顶级存储过程,并将失败的存储过程的名称和行号输出到 SQL 代理。

输出错误将如下所示:

以用户身份执行:NT AUTHORITY\NETWORK SERVICE。 *** [InnerInnerStoredProc2], 5. Errno 208: 无效的对象名称“NonExistentTable”。 [SQLSTATE 42000](错误 50000)启动 [SQLSTATE 01000](错误 0)。这一步失败了。

步骤摘要:

创建以下错误处理程序存储过程:

CREATE PROCEDURE error_handler_sp AS

DECLARE @errmsg   nvarchar(2048),
        @severity tinyint,
        @state    tinyint,
        @errno    int,
        @proc     sysname,
        @lineno   int

SELECT @errmsg = error_message(), @severity = error_severity(),   -- 10
       @state  = error_state(), @errno = error_number(),
       @proc   = error_procedure(), @lineno = error_line()

IF @errmsg NOT LIKE '***%'                                        -- 11  
BEGIN 
   SELECT @errmsg = '*** ' + coalesce(quotename(@proc), '<dynamic SQL>') + 
                    ', ' + ltrim(str(@lineno)) + '. Errno ' + 
                    ltrim(str(@errno)) + ': ' + @errmsg
   RAISERROR(@errmsg, @severity, @state)
END
ELSE
   RAISERROR(@errmsg, @severity, @state)
go

将顶级存储过程包装在 try catch 中,如下所示

BEGIN TRY
   SET NOCOUNT ON
   SET XACT_ABORT ON

EXEC InnerStoredProc1
EXEC InnerStoredProc2

END TRY
BEGIN CATCH
   IF @@trancount > 0 ROLLBACK TRANSACTION
   EXEC error_handler_sp
   RETURN 55555
END CATCH

Using the approach detailed at http://www.sommarskog.se/error_handling_2005.html seems to be working sufficiently so far. It has only required an update to the top level stored procedure and will output the name of the stored procedure that failed and the line number to SQL agent.

The output error will look like this:

Executed as user: NT AUTHORITY\NETWORK SERVICE. *** [InnerInnerStoredProc2], 5. Errno 208: Invalid object name 'NonExistentTable'. [SQLSTATE 42000] (Error 50000) Start [SQLSTATE 01000] (Error 0). The step failed.

Summary of steps:

Create the following error handler stored procedure:

CREATE PROCEDURE error_handler_sp AS

DECLARE @errmsg   nvarchar(2048),
        @severity tinyint,
        @state    tinyint,
        @errno    int,
        @proc     sysname,
        @lineno   int

SELECT @errmsg = error_message(), @severity = error_severity(),   -- 10
       @state  = error_state(), @errno = error_number(),
       @proc   = error_procedure(), @lineno = error_line()

IF @errmsg NOT LIKE '***%'                                        -- 11  
BEGIN 
   SELECT @errmsg = '*** ' + coalesce(quotename(@proc), '<dynamic SQL>') + 
                    ', ' + ltrim(str(@lineno)) + '. Errno ' + 
                    ltrim(str(@errno)) + ': ' + @errmsg
   RAISERROR(@errmsg, @severity, @state)
END
ELSE
   RAISERROR(@errmsg, @severity, @state)
go

Wrap the top level stored proc in a try catch as follows

BEGIN TRY
   SET NOCOUNT ON
   SET XACT_ABORT ON

EXEC InnerStoredProc1
EXEC InnerStoredProc2

END TRY
BEGIN CATCH
   IF @@trancount > 0 ROLLBACK TRANSACTION
   EXEC error_handler_sp
   RETURN 55555
END CATCH
梦忆晨望 2024-10-28 05:15:49

实现此目的的一种方法是向存储过程添加一些错误处理。这是我们在这里使用的一个简单方法,如下所示

declare
    @Error                 int
   ,@ErrorMsg              varchar(1000)
   ,@StepName              varchar(500)
   ,@ProcedureName         sysname
   ,@dtDateTime            datetime

select @ProcedureName = object_name(@@procid)

begin try
select @StepName = 'Step 01: Select from table
PRINT 'Start'
SELECT * FROM NonExistentTable
PRINT 'End'

end try

begin catch
   select @Error = @@ERROR
   set @ErrorMsg = @ProcedureName + ' Error: ' + @StepName
                                  + ', dbErrorNbr:' + IsNull(convert(varchar(10),@Error),'Null')
   raiserror (@ErrorMsg, 16, 1) with nowait
end catch

One way to do this would be add some error handling to the stored procedure. Here is a simple method we use here is something like this

declare
    @Error                 int
   ,@ErrorMsg              varchar(1000)
   ,@StepName              varchar(500)
   ,@ProcedureName         sysname
   ,@dtDateTime            datetime

select @ProcedureName = object_name(@@procid)

begin try
select @StepName = 'Step 01: Select from table
PRINT 'Start'
SELECT * FROM NonExistentTable
PRINT 'End'

end try

begin catch
   select @Error = @@ERROR
   set @ErrorMsg = @ProcedureName + ' Error: ' + @StepName
                                  + ', dbErrorNbr:' + IsNull(convert(varchar(10),@Error),'Null')
   raiserror (@ErrorMsg, 16, 1) with nowait
end catch
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文