SQL Server笔记 -- 第20章:TRY/CATCH

第20.1节:TRY/CATCH中的事务

这将由于无效的datetime而回滚两个插入

sql 复制代码
BEGIN TRANSACTION
BEGIN TRY
    INSERT INTO dbo.Sale(Price, SaleDate, Quantity)
    VALUES (5.2, GETDATE(), 1)
    INSERT INTO dbo.Sale(Price, SaleDate, Quantity)
    VALUES (5.2, 'not a date', 1)
    COMMIT TRANSACTION
END TRY
BEGIN CATCH
    ROLLBACK TRANSACTION --首先回滚,然后抛出
    THROW
END CATCH

这将提交两个插入:

sql 复制代码
BEGIN TRANSACTION
BEGIN TRY
    INSERT INTO dbo.Sale(Price, SaleDate, Quantity)
    VALUES (5.2, GETDATE(), 1)
    INSERT INTO dbo.Sale(Price, SaleDate, Quantity)
    VALUES (5.2, GETDATE(), 1)
    COMMIT TRANSACTION
END TRY
BEGIN CATCH
    THROW
    ROLLBACK TRANSACTION
END CATCH

第20.2节:在try-catch块中引发错误

RAISERROR函数将在TRY CATCH块中生成错误:

sql 复制代码
DECLARE @msg nvarchar(50) = 'Here is a problem!'
BEGIN TRY
    print 'First statement';
    RAISERROR(@msg, 11, 1);
    print 'Second statement';
END TRY
BEGIN CATCH
    print 'Error:' + ERROR_MESSAGE();
END CATCH

第二个参数大于10(本例中为11)的RAISERROR将停止TRY BLOCK中的执行并引发将在CATCH块中处理的错误。您可以使用ERROR_MESSAGE()函数访问错误消息。

此示例的输出为:

复制代码
First statement
Error:Here is a problem!

第20.3节:在try catch块中引发信息消息

第二个参数(严重级别)小于或等于10的RAISERROR不会引发异常。

sql 复制代码
BEGIN TRY
    print 'First statement';
    RAISERROR('Here is a problem!', 10, 15);
    print 'Second statement';
END TRY
BEGIN CATCH
    print 'Error:' + ERROR_MESSAGE();
END CATCH

在RAISERROR语句之后,第三条语句将被执行,CATCH块不会被调用。执行结果为:

复制代码
First statement
Here is a problem!
Second statement

第20.4节:重新引发RAISERROR生成的异常

您可以使用THROW语句重新引发在CATCH块中捕获的错误:

sql 复制代码
DECLARE @msg nvarchar(50) = 'Here is a problem! Area:''%s'' Line:''%i'''
BEGIN TRY
    print 'First statement';
    RAISERROR(@msg, 11, 1, 'TRY BLOCK', 2);
    print 'Second statement';
END TRY
BEGIN CATCH
    print 'Error:' + ERROR_MESSAGE();
    THROW;
END CATCH

请注意,在这种情况下,我们使用格式化参数(第四个和第五个参数)引发错误。如果您想在消息中添加更多信息,这可能很有用。

执行结果为:

复制代码
First statement
Error:Here is a problem! Area:'TRY BLOCK' Line:'2'
Msg 50000, Level 11, State 1, Line 26
Here is a problem! Area:'TRY BLOCK' Line:'2'

第20.5节:在TRY/CATCH块中引发异常

您可以在try catch块中引发异常:

sql 复制代码
DECLARE @msg nvarchar(50) = 'Here is a problem!'
BEGIN TRY
    print 'First statement';
    THROW 51000, @msg, 15;
    print 'Second statement';
END TRY
BEGIN CATCH
    print 'Error:' + ERROR_MESSAGE();
    THROW;
END CATCH

异常将在CATCH块中处理,然后使用不带参数的THROW重新引发。

复制代码
First statement
Error:Here is a problem!
Msg 51000, Level 16, State 15, Line 39
Here is a problem!

THROW与RAISERROR的相似之处和区别:

  • 建议新应用程序使用THROW而不是RAISERROR。
  • THROW可以使用任何数字作为第一个参数(错误号),RAISERROR只能使用sys.messages视图中的id
  • THROW的严重级别为16(无法更改)
  • THROW不能像RAISERROR那样格式化参数。如果需要,请使用FORMATMESSAGE函数作为RAISERROR的参数
相关推荐
xiaoqiMikko2 小时前
JVM 线上排查实战(七):jps 看不见它、jstack 连不上它,可它明明活得好好的
java·jvm
石头麻辣鱼2 小时前
Bamboo 调度系统 OceanBase 适配实战:存储过程迁移踩过的三个大坑
数据库
龙亘川2 小时前
数智驱动民政升级 精准守护民生保障
大数据·数据库·人工智能
狼爷2 小时前
Rust/Go/Java/Python/PHP 大比拼:负载下后端框架到底差多少?
java·后端·编程语言
念何架构之路2 小时前
zap扩展生态与总结
java·前端·数据库
晚安日记wanna3 小时前
MySQL 回表为什么这么慢?5 种优化手段逐个拆解
数据库·mysql·性能优化
第七页独白3 小时前
汽车零件厂如何通过 QMS 真正落地 IATF 16949——QMS软件系统:品质检验-内审稽核-8d客诉管理:全星质量管理软件系统
java·前端·数据库
晚安日记wanna3 小时前
索引建了却不走?7 个失效原因逐层排查
数据库·mysql·性能优化
QCoding3 小时前
Spring AI Alibaba Graph实战:从ReAct Agent到Workflow,企业AI复杂流程该如何编排?
java·人工智能
用户094248568033 小时前
第25章:Java虚拟线程(Project Loom)实战与调度协作
java·jvm