温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

在SQL Server中如何使用Try Catch处理异常

发布时间:2022-07-15 10:09:20 阅读:133 作者:iii 栏目:开发技术
亿速云云数据库,读写分离,安全稳定,弹性扩容,低至0.3元/天!! 点击查看>>

今天小编给大家分享一下在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 中的 Try-Catch 实现。

在下面的示例中,我们使用 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 块执行的错误消息文本。

在 SQL Server 中使用 try-catch 的示例

我们将使用下面的 Product 和 ProductSales 表来了解如何使用 RaiseError 和 @ERROR 系统定义函数来处理 SQL Server 中的错误。

Product (产品表)

ProductIDNamePriceQuantity
101Laptop15000100
102Desktop20000150
104Mobile3000200
105Tablet4000250

ProductSales (产品销售表)

ProductSalesIDProductIDQuantitySold
110110
210215
310430
410535

请使用以下 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'15000100)
INSERT INTO Product VALUES(102'Desktop'20000150)
INSERT INTO Product VALUES(103'Mobile'3000200)
INSERT INTO Product VALUES(104'Tablet'4000250)
GO
CREATE TABLE ProductSales
(
  ProductSalesId INT PRIMARY KEY,
  ProductId INT,
  QuantitySold INT
) 
GO
INSERT INTO ProductSales VALUES(110110)
INSERT INTO ProductSales VALUES(210215)
INSERT INTO ProductSales VALUES(310330)
INSERT INTO ProductSales VALUES(410435)
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 - @QuantityToSellWHERE 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

以上就是“在SQL Server中如何使用Try Catch处理异常”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注亿速云行业资讯频道。

亿速云「云数据库 MySQL」免部署即开即用,比自行安装部署数据库高出1倍以上的性能,双节点冗余防止单节点故障,数据自动定期备份随时恢复。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI

开发者交流群×