65.9K
CodeProject 正在变化。 阅读更多。
Home

SQL Server 2005 中的 Try 和 Catch 的乐趣

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.28/5 (11投票s)

2006年5月17日

3分钟阅读

viewsIcon

63860

本文介绍了 SQL Server 2005 中的异常处理改进。

引言

Try 和 Catch 在使用 C#、C++ 或其他高级语言编写代码的开发人员社区中非常流行。 指的是 Try-Catch 块的传统术语是异常处理。 异常处理只是应用程序预定义假设的违背。 它使我们能够在应用程序中提供可靠的数据/过程验证机制。 直到现在,SQL Server 还没有任何与之接近的对应物。 在 SQL Server 2005 之前,我们中的许多人依赖于变量 @@ERROR。 如果有任何异常行为,则 @@ERROR 将捕获一个非零值来指示错误代码。

要求

请确保手边有以下内容

  • SQL Server 2005(此处列出的任何版本)。
  • AdventureWorks 数据库(可以从 Microsoft 下载)。

请记住,默认情况下 SQL Server Express 版本中未安装 AdventureWorks。 简而言之,AdventureWorks 是一个虚构公司的数据库。 Microsoft 的示例使用此数据库作为提供概念验证的方式。

实现

我们中的许多人可能已经看到类似以下内容作为通知错误的方式

Declare @deadline int
set @deadline = 0

SELECT DaysToManufacture / @deadline
from AdventureWorks.Production.Product
WHERE ProductID = 921

if @@ERROR <> 0
begin
  print 'Error occurred'
end

这将输出

Msg 8134, Level 16, State 1, Line 1
Divide by zero error encountered.
Error Occurred

在大多数情况下,上述方法工作良好,但不如异常处理那么健壮。 它没有像 try..catch 块结构那样给我们带来灵活性。 让我们看看这在当前世界中会是什么样子

Declare @deadline int
set @deadline = 0

BEGIN TRY 
    SELECT DaysToManufacture / @deadline
    from AdventureWorks.Production.Product
    WHERE ProductID = 921
END TRY
BEGIN CATCH
  print 'Error Occurred'
END CATCH;

这将输出

 (0 row(s) affected)
Error Occurred

这是否意味着 @@ERROR 会消失? 不,仍然可以访问 @@ERROR 中包含的错误值。 但是,SQL Server 2005 定义了几个函数,它们的值只能在 Begin Catch...End Catch 中定义的范围内获得。 它们是 ERROR_NUMBER()ERROR_SEVERITY()ERROR_STATE()ERROR_PROCEDURE()ERROR_LINE()ERROR_MESSAGE()。 BOL 或 Books Online 有一个帮助程序,即 usp_GetErrorInfo,它可以获取与错误相关的信息。 本文后面的示例将使用此过程。

CREATE PROCEDURE usp_GetErrorInfo
AS
    SELECT
        ERROR_NUMBER() AS ErrorNumber,
        ERROR_SEVERITY() AS ErrorSeverity,
        ERROR_STATE() AS ErrorState,
        ERROR_PROCEDURE() AS ErrorProcedure,
        ERROR_LINE() AS ErrorLine,
        ERROR_MESSAGE() AS ErrorMessage;
GO

让我们稍微修改第一个脚本

Declare @deadline int
set @deadline = 0

BEGIN TRY 
    SELECT DaysToManufacture / @deadline
    from AdventureWorks.Production.Product
    WHERE ProductID = 921
END TRY
BEGIN CATCH
  EXECUTE usp_GetErrorInfo;
END CATCH;

这将输出

让我们修改第二个脚本以检查它在 Catch 块范围之外的行为

Declare @deadline int
set @deadline = 0

SELECT DaysToManufacture / @deadline
from AdventureWorks.Production.Product
WHERE ProductID = 921
 
SELECT usp_GetErrorInfo;

这将输出

到目前为止,已经介绍了多种处理异常的方法。 在 SQL Server 2005 中,可以使用嵌套的 Try..Catch 块。 这意味着在 Catch 块的范围内,可以检查涵盖预定义情况的逻辑是否再次被违反。 修改之前的查询使其看起来像

Declare @deadline int
set @deadline = 0

BEGIN TRY 
    SELECT DaysToManufacture / @deadline
    from AdventureWorks.Production.Product
    WHERE ProductID = 921
END TRY
BEGIN CATCH
  BEGIN TRY
    execute usp_GetErrorInfo
    select 'Error occurred at: ' + GetDate() – format exception
  END TRY
  BEGIN CATCH
    select 'Error Occurred'
  END CATCH;
END CATCH;

这将输出

结论

有人会想知道为什么有人会费心添加额外的语法。 相对于现有的实践而言,它似乎过于结构化和开销太大。 上面使用异常处理的示例允许执行流程顺利运行。 如果您比较 @@ERRORTry..Catch 之间的输出,那么可能会注意到 SQL Server 管理器没有突然转到显示警告的选项卡。 相反,它显示了可以在应用程序端轻松获取的结果集。 另外,尝试这样看待它,一位智者曾经说过,“汽车安装刹车是为了让人能够飞快地行驶”。 SQL Server 2005 中的异常处理是为了提供帮助。

© . All rights reserved.