SQL Server 2005 中的 Try 和 Catch 的乐趣






4.28/5 (11投票s)
2006年5月17日
3分钟阅读

63860
本文介绍了 SQL Server 2005 中的异常处理改进。
引言
Try 和 Catch 在使用 C#、C++ 或其他高级语言编写代码的开发人员社区中非常流行。 指的是 Try-Catch 块的传统术语是异常处理。 异常处理只是应用程序预定义假设的违背。 它使我们能够在应用程序中提供可靠的数据/过程验证机制。 直到现在,SQL Server 还没有任何与之接近的对应物。 在 SQL Server 2005 之前,我们中的许多人依赖于变量 @@ERROR
。 如果有任何异常行为,则 @@ERROR
将捕获一个非零值来指示错误代码。
要求
请确保手边有以下内容
请记住,默认情况下 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;
这将输出
结论
有人会想知道为什么有人会费心添加额外的语法。 相对于现有的实践而言,它似乎过于结构化和开销太大。 上面使用异常处理的示例允许执行流程顺利运行。 如果您比较 @@ERROR
和 Try..Catch
之间的输出,那么可能会注意到 SQL Server 管理器没有突然转到显示警告的选项卡。 相反,它显示了可以在应用程序端轻松获取的结果集。 另外,尝试这样看待它,一位智者曾经说过,“汽车安装刹车是为了让人能够飞快地行驶”。 SQL Server 2005 中的异常处理是为了提供帮助。