Sql语法高级应用之六:如何在Sql语句中如何使用TRY...CATCH

时间:2022-07-20 17:32:51

TRY...CATCH使用范例

BEGIN TRY
//逻辑语句块
END TRY
BEGIN CATCH
//Catch异常处理块
SET @msg = ERROR_MESSAGE();
PRINT @msg;
END CATCH;

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

  • 每个 TRY...CATCH 构造都必须位于一个批处理、存储过程或触发器中。例如,不能将 TRY 块放置在一个批处理中而将关联的 CATCH 块放置在另一个批处理中。

  • 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 使用下列错误函数来捕获错误信息:

  • ERROR_NUMBER() 返回错误号。

  • ERROR_MESSAGE() 返回错误消息的完整文本。此文本包括为任何可替换参数(如长度、对象名或时间)提供的值。

  • ERROR_SEVERITY() 返回错误严重性。

  • ERROR_STATE() 返回错误状态号。

  • ERROR_LINE() 返回导致错误的例程中的行号。

  • ERROR_PROCEDURE() 返回出现错误的存储过程或触发器的名称。

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

BEGIN TRY
-- Generate divide-by-zero error.
SELECT 1/0;
END TRY
BEGIN CATCH
-- Execute the error retrieval routine.
EXECUTE usp_GetErrorInfo;
END CATCH;
GO

编译错误和语句级重新编译错误

对于与 TRY...CATCH 构造在同一执行级别发生的错误,TRY...CATCH 将不处理以下两类错误:

  • 编译错误,例如阻止批处理执行的语法错误。

  • 语句级重新编译过程中出现的错误,例如由于名称解析延迟而造成在编译后出现对象名解析错误。

当包含 TRY...CATCH 构造的批处理、存储过程或触发器生成其中一种错误时,TRY...CATCH 构造将不处理这些错误。这些错误将返回到调用生成错误的例程的应用程序或批处理。例如,下面的代码示例显示导致语法错误的 SELECT 语句。如果在 SQL Server Management Studio 查询编辑器中执行此代码,则由于批处理无法编译,执行将不启动。错误将返回到查询编辑器,将不会由 TRY...CATCH 捕获。

USE Wot_Inventory;
GO BEGIN TRY
-- This PRINT statement will not run because the batch
-- does not begin execution.
PRINT N'Starting execution'; -- This SELECT statement contains a syntax error that
-- stops the batch from compiling successfully.
SELECT ** FROM Wot_Inventory.dbo.Invoice
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber,
ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
GO

与上述示例中的语法错误不同,语句级重新编译过程中发生的错误不会阻碍批处理进行编译,但是一旦语句重新编译失败,它会立即终止批处理。例如,如果批处理含有两条语句并且第二条语句引用的表不存在,则延迟的名称解析会使该批处理成功进行编译并开始执行(无需将缺少的表绑定到查询计划),直到重新编译该语句为止。批处理到达引用缺失表的语句时将停止运行,并返回一个错误。在发生错误的执行级别,TRY...CATCH 构造将不处理此类错误。

有关详细信息,请参阅处理数据库引擎错误中的“在 Transact-SQL 中使用 TRY...CATCH”一节。

PS:欢迎扫描下方二维码或点击链接,加入QQ群

Sql语法高级应用之六:如何在Sql语句中如何使用TRY...CATCH

Sql语法高级应用之六:如何在Sql语句中如何使用TRY...CATCH