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

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

4

2 回答 2

2

到目前为止,使用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
于 2011-03-11T00:39:11.697 回答
1

一种方法是向存储过程添加一些错误处理。这是我们在这里使用的一个简单方法是这样的

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
于 2011-03-10T23:40:53.787 回答