SQL Server中Try Catch处理异常的操作是什么
Admin 2022-08-03 群英技术资讯 1208 次浏览
今天这篇我们来学习和了解“SQL Server中Try Catch处理异常的操作是什么”,下文的讲解详细,步骤过程清晰,对大家进一步学习和理解“SQL Server中Try Catch处理异常的操作是什么”有一定的帮助。有这方面学习需要的朋友就继续往下看吧!从 SQL Server 2005 开始,我们在TRY 和 CATCH块的帮助下提供了结构错误处理机制。使用TRY-CATCH的语法如下所示。
BEGIN TRY --这里写可能导致错误的语句 END TRY BEGIN CATCH --当错误发生后,这里的语句将会被执行 END CATCH -- 其他语句
有可能抛出异常的SQL 语句需要放在BEGIN TRY和END TRY块之间。如果在 TRY 块中发生异常,则控制权立即转移到相应的CATCH块。如果 TRY 块中没有发生异常,则直接跳过CATCH块,执行CATCH块之后的语句。
注意:被 CATCH 捕获的错误不会返回给调用应用程序。如果要将错误信息返回给调用应用程序,则需要将 RAISERROR() 函数显式与 catch 块一起使用。在之前的文章中,我们讨论了如何使用 RAISERROR() 函数显式地引发错误。参考: SQL Server 中的异常处理
在下面的示例中,我们使用 SQL Server TRY CATCH 实现和用户定义的错误语句来创建一个用于除以 2 个变量值的存储过程。
IF OBJECT_ID('spDivideTwoNumbers','P') IS NOT NULL
DROP PROCEDURE spDivideTwoNumbers
GO
CREATE PROCEDURE spDivideTwoNumbers(
@Number1 INT,
@Number2 INT
)
AS
BEGIN
DECLARE @Result INT
SET @Result = 0
BEGIN TRY
SET @Result = @Number1 / @Number2
PRINT '结果是: ' + CAST(@Result AS VARCHAR)
END TRY
BEGIN CATCH
PRINT '第二个数字不能为0'
END CATCH
END
让我们来测试一下这个存储过程
exec spDivideTwoNumbers 100,1
输出: 结果是: 100
exec spDivideTwoNumbers 100,0
输出: 第二个数字不能为0
当我们用正确的值执行上述存储过程时,程序就不会出现错误。这意味着在执行完 try 块中的所有语句后,控件直接跳转到存在于 catch 块之后的语句,而不执行 catch 块。
如果在执行过程中,即在try块中发生任何错误,那么在这种情况下,从发生错误的行开始,控制权直接跳转到catch块。所以 try 块中的其余语句将不会执行,而 catch 块将执行。
注意:在上面的程序中,当错误发生时,我们会显示一条用户自定义的错误消息“第二个数字不能为0”。然而,我们还可以通过调用函数 Error_Message 来显示原始错误消息。为了测试这个重写catch块内的代码如下
ALTER PROCEDURE spDivideTwoNumbers(
@Number1 INT,
@Number2 INT
)
AS
BEGIN
DECLARE @Result INT
SET @Result = 0
BEGIN TRY
SET @Result = @Number1 / @Number2
PRINT '结果是: ' + CAST(@Result AS VARCHAR)
END TRY
BEGIN CATCH
PRINT ERROR_MESSAGE()
END CATCH
END
再次执行: exec spDivideTwoNumbers 100,0
输出: 遇到以零作除数错误。
ERROR_MESSAGE 是系统函数, 此函数返回导致 TRY...CATCH 构造的 CATCH 块执行的错误消息文本。
我们将使用下面的 Product 和 ProductSales 表来了解如何使用 RaiseError 和 @ERROR 系统定义函数来处理 SQL Server 中的错误。
Product (产品表)
| ProductID | Name | Price | Quantity |
|---|---|---|---|
| 101 | Laptop | 15000 | 100 |
| 102 | Desktop | 20000 | 150 |
| 104 | Mobile | 3000 | 200 |
| 105 | Tablet | 4000 | 250 |
ProductSales (产品销售表)
| ProductSalesID | ProductID | QuantitySold |
|---|---|---|
| 1 | 101 | 10 |
| 2 | 102 | 15 |
| 3 | 104 | 30 |
| 4 | 105 | 35 |
请使用以下 SQL 脚本创建并使用示例数据填充 Product 和 ProductSales 表。
IF OBJECT_ID('dbo.Product','U') IS NOT NULL
DROP TABLE dbo.Product
IF OBJECT_ID('dbo.ProductSales','U') IS NOT NULL
DROP TABLE dbo.ProductSales
GO
CREATE TABLE Product
(
ProductID INT PRIMARY KEY,
Name VARCHAR(40),
Price INT,
Quantity INT
)
GO
INSERT INTO Product VALUES(101, 'Laptop', 15000, 100)
INSERT INTO Product VALUES(102, 'Desktop', 20000, 150)
INSERT INTO Product VALUES(103, 'Mobile', 3000, 200)
INSERT INTO Product VALUES(104, 'Tablet', 4000, 250)
GO
CREATE TABLE ProductSales
(
ProductSalesId INT PRIMARY KEY,
ProductId INT,
QuantitySold INT
)
GO
INSERT INTO ProductSales VALUES(1, 101, 10)
INSERT INTO ProductSales VALUES(2, 102, 15)
INSERT INTO ProductSales VALUES(3, 103, 30)
INSERT INTO ProductSales VALUES(4, 104, 35)
GO
在 SQL Server 中使用 TRY Catch 实现产品销售的存储过程
CREATE PROCEDURE spSellProduct
@ProductID INT,
@QuantityToSell INT
AS
BEGIN
-- 首先我们需要检查待销售产品的可用库存
DECLARE @StockAvailable INT
SELECT @StockAvailable = QuantityAvailable FROM Product WHERE ProductId = @ProductId
--如果可用库存小于要销售的数量,抛出错误
IF(@StockAvailable< @QuantityToSell)
BEGIN
Raiserror('可用库存不足',16,1)
END
-- 如果可用库存充足
ELSE
BEGIN
BEGIN TRY
-- 我们需要开启一个事务
BEGIN TRANSACTION
-- 首先做减库存操作
UPDATE Product SET Quantity = (Quantity - @QuantityToSell) WHERE ProductID = @ProductID
-- 计算当前最大的产品销售ID,即 MaxProductSalesId
DECLARE @MaxProductSalesId INT
SELECT @MaxProductSalesId = CASE
WHEN MAX(ProductSalesId) IS NULL THEN 0
ELSE MAX(ProductSalesId)
END
FROM ProductSales
-- 把 @MaxProductSalesId 加一, 所以我们会避免主键冲突
--(解释下,建表的时候,没有设置主键自增,所以需要人工处理自增)
Set @MaxProductSalesId = @MaxProductSalesId + 1
-- 把销售的产品数量记录到ProductSales表中
INSERT INTO ProductSales VALUES (@MaxProductSalesId, @ProductId, @QuantityToSell)
-- 最后,提交事务
COMMIT TRANSACTION
END TRY
BEGIN CATCH
-- 如果发生了异常,回滚事务
ROLLBACK TRANSACTION
-- 输出错误详情
SELECT ERROR_NUMBER() as ErrorNumber,
ERROR_MESSAGE() as ErrorMessage,
ERROR_PROCEDURE() as ErrorProcedure,
ERROR_STATE() as ErrorState,
ERROR_SEVERITY() as ErrorSeverity,
ERROR_LINE() as ErrorLine
END CATCH
End
END
在存储过程 spSellProduct 中,Begin Transaction 和 Commit Transaction 语句被包装在 Begin Try 和 End Try 块之间。如果包含在 BEGIN TRY 和 END TRY 块中的代码没有发生错误,则执行 COMMIT TRANSACTION 语句并将更改永久保存到数据库。
如果在 try 块中发生错误,则立即跳转到 CATCH 块,并且在 CATCH 块中,我们正在回滚事务。因此,使用 Try/Catch 构造处理错误比使用 SQL Server 中的 @@Error 系统函数要容易得多。
SQL Server 还提供了一些我们可以在 CATCH 块范围内使用的内置函数,这些函数用于检索有关发生的错误的更多信息,如果这些函数在 CATCH 块范围之外执行,它们将返回 NULL。
注意:我们不能在用户定义的函数中使用 TRY/CATCH
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
master数据库损坏怎么办?一些朋友在使用SQL Server 2008 时,遇到master数据库损坏的情况不知道怎么解决,而针对不同原因导致master数据库损坏的解决方法不同,下面我们就来具体看看。
这篇文章主要介绍了SQL SERVER修改函数名容易引发的问题分析的相关资料,需要的朋友可以参考下
SQL FULL OUTER JOIN 关键字作用是什么?当左(表1)或右(表2)表记录匹配时,FULL OUTER JOIN关键字将返回所有记录。 注意: FULL OUTER JOIN可能会返回非常大的结果集!
这篇文章介绍了SQL Server分页的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
以技能为基础的企业里最有价值的财物莫过所以客户或者其数据库中的产品信息了。因此,在这样的企业中,确保数据库免受外界进犯是数据库管理的重要环节。
成为群英会员,开启智能安全云计算之旅
立即注册关注或联系群英网络
7x24小时售前:400-678-4567
7x24小时售后:0668-2555666
24小时QQ客服
群英微信公众号
CNNIC域名投诉举报处理平台
服务电话:010-58813000
服务邮箱:service@cnnic.cn
投诉与建议:0668-2555555
Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 ICP核准(ICP备案)粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008