可以使用 TRY...CATCH 构造(类似于 Microsoft Visual C++ 和 Microsoft Visual C# 语言的异常处理功能)来处理 Transact-SQL 代码中的错误。TRY…CATCH 构造包括两部分:一个 TRY 块和一个 CATCH 块。如果在 TRY 块中所包含的 Transact-SQL 语句中检测到错误条件,控制将被传递到 CATCH 块(可在此块中处理该错误)。

CATCH 块处理该异常错误后,控制将被传递到 END CATCH 语句后面的第一个 Transact-SQL 语句。如果 END CATCH 语句是存储过程或触发器中的最后一条语句,控制将返回到调用该存储过程或触发器的代码。将不执行 TRY 块中生成错误的语句后面的 Transact-SQL 语句。

如果 TRY 块中没有错误,控制将传递到关联的 END CATCH 语句后紧跟的语句。如果 END CATCH 语句是存储过程或触发器中的最后一条语句,控制将传递到调用该存储过程或触发器的语句。

TRY 块以 BEGIN TRY 语句开头,以 END TRY 语句结尾。在 BEGIN TRY 和 END TRY 语句之间可以指定一个或多个 Transact-SQL 语句。

CATCH 块必须紧跟 TRY 块。CATCH 块以 BEGIN CATCH 语句开头,以 END CATCH 语句结尾。在 Transact-SQL 中,每个 TRY 块仅与一个 CATCH 块相关联。

 

 

 

使用 TRY...CATCH


使用 TRY...CATCH 构造时,请遵循下列规则和建议:

  • 每个 TRY...CATCH 构造都必须包含在一个批处理、存储过程或触发器中。例如,不能将 TRY 块放置在一个批处理中而将关联的 CATCH 块放置在另一个批处理中。下面的脚本将生成一个错误:

 

复制代码

BEGIN TRY SELECT * FROM sys.messages WHERE message_id = 21;END TRYGO-- The previous GO breaks the script into two batches,-- generating syntax errors. The script runs if this GO-- is removed.BEGIN CATCH SELECT ERROR_NUMBER() AS ErrorNumber;END CATCH;GO

  • CATCH 块必须紧跟 TRY 块。
  • TRY...CATCH 构造可以进行嵌套,也就是说在其他 TRY 和 CATCH 块内放置 TRY...CATCH 构造。当嵌套的 TRY 块中出现错误时,程序控制将传递到与嵌套的 TRY 块关联的 CATCH 块。
  • 若要处理给定的 CATCH 块中出现的错误,请在指定的 CATCH 块中编写 TRY...CATCH 块。
  • TRY...CATCH 块不处理导致数据库引擎 终止连接的严重性为 20 或更高的错误。但是,只要连接不终止,TRY...CATCH 就会处理严重性为 20 或更高的错误。
  • 严重性为 10 或更低的错误被视为警告或信息性消息,TRY...CATCH 块不处理此类错误。
  • 即使批处理位于 TRY...CATCH 构造的作用域内,关注消息仍将终止该批处理。分布式事务失败时,Microsoft 分布式事务处理协调器 (MS DTC) 将发送关注消息。MS DTC 用于管理分布式事务。

注意:

如果在 TRY 块的作用域内执行分布式事务且发生错误,执行将传递到关联的 CATCH 块。分布式事务进入无法提交状态且必须进行回滚。CATCH 块中的执行可能由管理分布式事务的 Microsoft 分布式事务处理协调器中断。发生错误时,MS DTC 将异步通知参与分布式事务的所有服务器,并终止分布式事务中涉及的所有任务。此类通知以关注消息的形式发送(TRY...CATCH 构造不处理此类通知),批处理将被终止。有关详细信息,请参阅分布式事务(数据库引擎)。

 


错误函数



TRY...CATCH 使用错误函数来捕获错误信息。

  • ERROR_NUMBER() 返回错误号。
  • ERROR_MESSAGE() 返回错误消息的完整文本。此文本包括为任何可替换参数(如长度、对象名称或时间)提供的值。
  • ERROR_SEVERITY() 返回错误严重性。
  • ERROR_STATE() 返回错误状态号。
  • ERROR_LINE() 返回导致错误的例程中的行号。
  • ERROR_PROCEDURE() 返回出现错误的存储过程或触发器的名称。

可以使用这些函数从 TRY...CATCH 构造的 CATCH 块的作用域内的任何位置检索错误信息。如果在 CATCH 块的作用域之外调用错误函数,错误函数将返回 NULL。在 CATCH 块内执行存储过程时,可以在存储过程中引用错误函数并将其用于检索错误信息。如果这样做,将不必在每个 CATCH 块中键入错误处理代码。在下面的代码示例中,TRY 块中的 SELECT 语句将生成一个被零除错误。该错误将由 CATCH 块处理,它将使用存储过程返回错误信息。