我有一个似乎没有正确记录错误的存储过程。
代码错误,但catch块似乎没有生效。
try块相当长 - 但是错误部分很简单并且在结尾处是正确的,所以我已经准确了。
BEGIN TRY
insert into tbl_X
select * from #temp_tbl_Y
RETURN 1
END TRY
BEGIN CATCH
Insert Into ExtractsErrorLog
SELECT
getdate() as ErrorDate
,object_name(@@procid) as ProcedureName
,ERROR_NUMBER() as ErrorNumber
,ERROR_LINE() as ErrorLine
,ERROR_MESSAGE() as ErrorMessage
;
DECLARE @errormessage as varchar(max);
DECLARE @errorseverity as int;
DECLARE @errorstate as int;
set @errormessage = ERROR_MESSAGE();
set @errorseverity = ERROR_SEVERITY();
set @errorstate = ERROR_STATE();
RAISERROR (@errormessage,
@errorseverity,
@errorstate
);
END CATCH;
proc失败的错误是我们的老朋友 “列名或提供的值数与表定义不匹配。” 我已经修复了这个错误 - 这是一个愚蠢的懒惰错误 - 但我很困惑为什么我的错误记录过程似乎没有工作 - 没有行插入我的ExtractsErrorLog表。
答案 0 :(得分:7)
TSQL' TRY...CATCH
没有发现错误。这个错误属于"编译/重新编译"在同一级别的执行中,CATCH
块"未处理类型错误"。
来自MSDN:
当CATCH块不处理以下类型的错误 它们与TRY ... CATCH结构处于相同的执行级别:
编译阻止批处理的错误,例如语法错误 运行
语句级重新编译期间发生的错误,例如 作为编译后发生的对象名称解析错误,因为 延迟名称解析
...
您可以使用TRY ... CATCH来处理编译期间发生的错误 或通过执行错误生成来进行语句级重新编译 代码在TRY块中的单独批处理中。例如,你这样做 这可以通过将代码放在存储过程中或通过执行 使用sp_executesql的动态Transact-SQL语句。这允许 TRY ... CATCH在比执行更高的执行级别捕获错误 错误发生。例如,以下代码显示已存储 生成对象名称解析错误的过程。批次 包含TRY ... CATCH结构正在更高级别执行 比存储过程;和错误,发生在较低的 等级,被捕获。
我遇到了类似的问题,脚本在TRY...CATCH
内创建了一个事务,如果失败,它将ROLLBACK
该事务。事务中的一个语句抛出同样的错误并导致事务永远不会被关闭,因为从未输入CATCH
。
正如MSDN文章中所提到的,另一种方法是从INSERT
语句中创建存储过程,然后在try / catch中调用它。如果sproc错误,您在尝试创建它时会捕获编译错误。如果表定义稍后更改为使sproc无效,则TRY...CATCH
将为您捕获异常。
如果你希望它们都存在于一个脚本中,你可以将其设为temporary stored procedure,但是在创建sprocs时需要处理编译错误。它不漂亮,但它会起作用:
-- Creating error sproc to re-use code
CREATE PROCEDURE #HandleError AS
Insert Into ExtractsErrorLog
SELECT GETDATE() as ErrorDate
,object_name(@@procid) as ProcedureName
,ERROR_NUMBER() as ErrorNumber
,ERROR_LINE() as ErrorLine
,ERROR_MESSAGE() as ErrorMessage;
DECLARE @errormessage as varchar(max);
DECLARE @errorseverity as int;
DECLARE @errorstate as int;
set @errormessage = ERROR_MESSAGE();
set @errorseverity = ERROR_SEVERITY();
set @errorstate = ERROR_STATE();
RAISERROR ( @errormessage,
@errorseverity,
@errorstate);
GO
-- Create a stored procedure of our INSERT and catch any compilation errors
CREATE PROCEDURE #TEST AS
insert into tbl_X
select * from #temp_tbl_Y
GO
IF (@@ERROR <> 0) BEGIN
exec #HandleError
-- If there was an error creating the sprocs, don't continue to the next batch
RETURN
END
-- If compilation succeeded, then run the sproc
BEGIN TRY
exec #TEST
RETURN
END TRY
BEGIN CATCH
exec #HandleError
END CATCH;
答案 1 :(得分:0)
我在INSERT语句之前在CATCH块中使用了THROW进行记录-并遇到了与您相同的问题。一旦我在记录INSERT语句后移动THROW,它就会起作用。看起来THROW可能会终止会话。
您未在代码示例中使用THROW,但认为这可能会对其他人有所帮助。
答案 2 :(得分:-1)
这是你的RETURN:“无条件退出查询或过程.RETURN立即完成,可以在任何时候用于退出过程,批处理或语句块。”