TSQL's TRY...CATCH
没有捕获该错误。该错误属于“编译/重新编译”类型错误,不由CATCH
块“在同一执行级别内”。
From MSDN http://msdn.microsoft.com/en-us/library/ms175976.aspx:
以下类型的错误不会由 CATCH 块处理:
它们发生在与 TRY…CATCH 构造相同的执行级别:
...
可以使用TRY…CATCH来处理编译过程中出现的错误
或通过执行生成错误的语句级重新编译
TRY 块中单独批处理的代码。例如,你做
通过将代码放入存储过程或执行
使用 sp_executesql 的动态 Transact-SQL 语句。这允许
TRY…CATCH 在比执行级别更高的执行级别捕获错误
错误发生。例如,以下代码显示了存储的
生成对象名称解析错误的过程。该批次
包含 TRY…CATCH 构造的内容正在更高级别执行
比存储过程;和错误,发生在较低的
水平,被抓住。
我在一个脚本中创建事务时遇到了类似的问题TRY...CATCH
那会ROLLBACK
如果交易失败。事务内的一条语句引发了同样的错误,并导致事务永远不会关闭,因为CATCH
从未进入过。
正如 MSDN 文章中提到的,一种替代方法是从您的存储过程中创建一个存储过程。INSERT
声明,然后在你的 try/catch 中调用它。如果存储过程错误,您将在尝试创建它时捕获编译错误。如果表定义稍后发生更改以使存储过程无效,则TRY...CATCH
将为您捕获异常。
如果您希望所有内容都存在于一个脚本中,您可以将其制作为临时存储过程 http://technet.microsoft.com/en-us/library/ms190669(v=sql.105).aspx/#sectionToggle1,但是您需要在创建存储过程时处理编译错误。它并不漂亮,但它会起作用:
-- 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;