可以使用 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 TRY GO -- 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 块处理,它将使用存储过程返回错误信息。