Sql server 在TSQL上尝试捕获-捕获未捕获
我有一个存储过程,它似乎没有正确地记录错误 代码出错,但catch块似乎没有生效 try块相当长,但是出错部分很简单,并且正好在末尾,所以我已经确定了这一点Sql server 在TSQL上尝试捕获-捕获未捕获,sql-server,sql-server-2008,tsql,try-catch,Sql Server,Sql Server 2008,Tsql,Try Catch,我有一个存储过程,它似乎没有正确地记录错误 代码出错,但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_
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;
进程失败的错误是我们的老朋友
“提供的值的列名或数目与表定义不匹配。”
我已经修复了这个错误-这是一个愚蠢的懒惰错误-但我很困惑为什么我的错误日志记录过程似乎没有工作-没有任何行被插入到我的ExtractErrorLog表中。这是您的返回:“无条件退出查询或过程。RETURN是即时且完整的,可以在任何时候用于从过程、批处理或语句块中退出。“TSQL的
TRY…CATCH
不会捕获该错误。该错误属于“编译/重新编译”类型的错误,而CATCH
块“在同一执行级别内”不会处理该错误。”
发件人:
以下类型的错误不由CATCH块处理:
它们发生在与TRY…CATCH构造相同的执行级别:
- 编译错误,如语法错误,会阻止批处理 跑步
- 语句级重新编译期间发生的错误,例如 编译后发生的对象名称解析错误,因为 延迟名称解析的实现
TRY…CATCH
中创建了一个事务,如果事务失败,它将回滚该事务。事务中的一条语句抛出了相同的错误,并导致该事务永远无法关闭,因为从未输入CATCH
正如MSDN文章中提到的,一种替代方法是从INSERT
语句中创建一个存储过程,然后在try/catch中调用它。如果存储过程出错,您将在尝试创建时捕获编译错误。如果稍后表定义更改为使存储过程无效,则try…catch
将为您捕获异常
如果希望所有脚本都存在于一个脚本中,则可以将其设为一个脚本,但在创建存储过程时需要处理编译错误。这并不漂亮,但可以工作:
-- 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;
--创建错误存储过程以重复使用代码
创建过程#HandleError AS
插入到ExtractErrorLog中
选择GETDATE()作为ErrorDate
,对象名称(@@PROCEID)为ProcedureName
,ERROR_NUMBER()作为ErrorNumber
,ERROR_LINE()作为ErrorLine
,ERROR_MESSAGE()作为ErrorMessage;
将@errormessage声明为varchar(最大值);
将@errorseverity声明为int;
声明@errorstate为int;
设置@errormessage=ERROR_MESSAGE();
设置@errorseverity=ERROR_SEVERITY();
设置@errorstate=ERROR_STATE();
RAISERROR(@errormessage,
@错误严重性,
@错误状态);
去
--创建INSERT的存储过程并捕获任何编译错误
创建程序#测试为
插入tbl_X
从临时任务中选择*
去
如果(@@0错误)开始
执行官#HandleError
--如果创建存储过程时出错,请不要继续下一批
返回
结束
--如果编译成功,则运行存储过程
开始尝试
执行测试
返回
结束尝试
开始捕捉
执行官#HandleError
末端捕捉;
我在日志记录的INSERT语句之前使用了CATCH块中的THOW,并且遇到了与您相同的问题。一旦我在日志记录INSERT语句之后移动THOW,它就工作了。看起来THOW可能会终止会话
您在代码示例中不使用THROW,但认为这可能会帮助其他人。这是一个编译时错误,请参见:您可以发布extractersErrorLog的表定义吗?
?谢谢Ivan-这很有意义-该线程也提供了一个解决方法。很抱歉,错过了它并重新发布了。我读到catch没有捕获compile-但我没有意识到这会是一个编译错误。有人知道在线上有没有一个指南来了解编译/重新编译时会发生什么错误。我现在可以理解为什么会出现这种情况,我想也会丢失一些表等。但是我想确定一下,我没有太多关于这方面的详细信息。@DanBennett,你知道吗找到解决方法吗?我期待着这个错误,并希望尝试|捕获它以在它发生时运行不同的逻辑-解决方法只是将错误移动到内部SP调用。嗨@ColinMac-查看Ivan G消息中的链接,它指向资源,其中一些指向选项。我们最终没有这样做,因为我们觉得选项捕获错误增加了工时代码复杂性,这超过了好处。YMMV未达到返回值
,如“列名或提供的值数量与表定义不匹配所示。“
error…谢谢拉塞尔-虽然我同意迈克尔的观点,但我相当肯定没有收到回报。谢谢大家在这方面的帮助-我想Ivan已经有了上面的答案。所以基本上,如果一个对象被重命名为t