群里一个朋友遇到一个TRY CATCH的小问题,测试后发现是自己从来没有考虑的情况,写篇blog加深下印象

--=========================================================

在MSDN上对TRY CATCH有如下描述:

对 Transact-SQL 实现与 Microsoft Visual C# 和 Microsoft Visual C++ 语言中的异常处理类似的错误处理。Transact-SQL 语句组可以包含在 TRY 块中。如果 TRY 块内部发生错误,则会将控制传递给 CATCH 块中包含的另一个语句组。

--=========================================================

在TRY CATCH未出现之前,我们使用@@ERROR,ERROR_STATE()等来判断语句是否正常运行,再根据情况来处理事务,随着TRY CATCH的出现,我们可以将事务语句写成如下方式:

--开启事务
BEGIN TRAN
BEGIN TRY
--执行一些逻辑操作
INSERT INTO TB1(ID)VALUES(1)
--提交事务
COMMIT TRAN
END TRY
BEGIN CATCH
--回滚事务
ROLLBACK TRAN
END CATCH

可当我们执行以下语句(不创建临时表#TB)

BEGIN TRAN
BEGIN TRY INSERT INTO #TB SELECT 1 PRINT 'COMMIT TRAN'; COMMIT TRAN;
END TRY
BEGIN CATCH SELECT ERROR_MESSAGE() AS ErrorMessage
,ERROR_SEVERITY() AS ErrorSeverity
,ERROR_STATE() AS ErrorState PRINT 'ROLLBACK TRAN';
ROLLBACK TRAN; END CATCH

由于#TB没有创建,因此在执行中发生异常,错误提示如下:

消息 102,级别 15,状态 1,第 24 行
“对”附近有语法错误。

这个错误很容易理解,因为#TB不存在,但这不是重点,重点是CATCH部分的语句没有被执行,事务没有被提交也没有被回滚(如果程序中有类似问题,那就严重咯)。

继续阅读MSDN,可以找到如下解释:

不受 TRY…CATCH 构造影响的错误
TRY…CATCH 构造在下列情况下不捕获错误: 严重级别为 10 或更低的警告或信息性消息。 严重级别为 20 或更高且终止会话的 SQL Server 数据库引擎任务处理的错误。如果所发生错误的严重级别为 20 或更高,而数据库连接未中断,则 TRY…CATCH 将处理该错误。 需要关注的消息,如客户端中断请求或客户端连接中断。 当系统管理员使用 KILL 语句终止会话时。 如果以下类型的错误的发生级别与 TRY…CATCH 构造的执行等级相同,则 CATCH 块不会处理这些错误: 编写错误,例如禁止运行批处理的语法错误。 语句级重新编写过程中出现的错误,例如由于名称解析延迟而造成在编写后出现对象名解析错误。 这些错误会被返回到运行批处理、存储过程或触发器的级别。

经过对比分析,我们遇到的问题应该属于“语句级重新编写过程中出现的错误,例如由于名称解析延迟而造成在编写后出现对象名解析错误。”的情况。

--==============================================================

如果有类似的问题,我们应该如何处理呢?

解决办法1: 在对#TB处理前先判断其是否存在

解决办法2:将对#TB的操作语句放入的EXEC(@SQL)

BEGIN TRAN
BEGIN TRY EXEC('INSERT INTO #TB SELECT 1') PRINT 'COMMIT TRAN'; COMMIT TRAN;
END TRY
BEGIN CATCH SELECT ERROR_MESSAGE() AS ErrorMessage
,ERROR_SEVERITY() AS ErrorSeverity
,ERROR_STATE() AS ErrorState PRINT 'ROLLBACK TRAN';
ROLLBACK TRAN; END CATCH

执行以上代码,会发现同样是严重级别16的错误,这次可以被传递到CATCH块中处理。
--=======================================================

很多人说细节决定成败,学习SQL SERVER的路上,有很多类似的小知识点,平时很难遇到,遇到时也很容易颠覆下我们自认为的“真理”,这个时候,多看看MSDN还是很管用的!

曲演杂坛--使用TRY CATCH应该注意的一个小细节的更多相关文章

  1. 曲演杂坛--一条DELETE引发的思考

    原文:曲演杂坛--一条DELETE引发的思考 场景介绍: 我们有一张表,专门用来生成自增ID供业务使用,表结构如下: CREATE TABLE TB001 ( ID ,) PRIMARY KEY, D ...

  2. 曲演杂坛--蛋疼的ROW_NUMBER函数

    使用ROW_NUMBER来分页几乎是家喻户晓的东东了,而且这东西简单易用,简直就是程序员居家必备之杀器,然而ROW_NUMBER也不是一招吃遍天下鲜的无敌BUG般存在,最近就遇到几个小问题,拿出来供大 ...

  3. 曲演杂坛--当ROW_NUMBER遇到TOP

    值班期间研发同事打来电话,说应用有超时,上服务器上检查发现有SQL大批量地执行,该SQL消耗IO资源较多,导致服务器存在IO瓶颈,细看SQL,发现自己都被整蒙了,不知道这SQL是要干啥,处理完问题赶紧 ...

  4. 曲演杂坛--特殊字符/生僻字与varchar

    对于中文版的SQL SERVER,默认安装后使用的默认排序规则为Chinese_PRC_CI_AS,在此排序规则下,使用varchar类型来可以“正常存取”存放中文字符以及一些东南亚国家的字符,同时v ...

  5. 曲演杂坛--使用CTE时踩的小坑:No Join Predicate

    在一次系统优化中,意外发现一个比较“坑”的SQL,拿出来供大家分享. 生成演示数据: --====================================== --检查测试表是否存在 IF(O ...

  6. 曲演杂坛--为什么SELECT语句会被其他SELECT阻塞?

    很多刚入门的DBA在捕获阻塞得时候,会问这么一个问题“为什么这个SELECT语句被那个SELECT语句阻塞了,难道不是共享锁么?” 让我们来做个小测试,首先准备一些测试数据: --========== ...

  7. 曲演杂坛--EXISTS语句

    通常在我写EXISTS语句时,我会写成IF EXISTS(SELECT TOP(1) 1 FROM XXX),也没细细考究过为什么要这么写,只是隐约认为这样写没有啥问题,那今天就深究下吧! 首先准备测 ...

  8. 曲演杂坛--SQLCMD下执行命令失败但没有任何错误提示的坑

    今天使用SQLCMD导入到SQL SERVER数据库中,看着数据文件都成功执行,但是意外发现有一个文件数据没有成功导入,但执行不报错,很容易导致问题被忽略. 使用存在问题的文件做下测试,从界面上看几行 ...

  9. 曲演杂坛--Update的小测试

    今天偶然想起一个UPDATE相关的小问题,正常情况下,如果我们将UPDATE改写成与之对应的SELECT语句,其SELECT查询结果应与UPDATE的目标表存在一对一的关系,例如: 对于UPDATE语 ...

随机推荐

  1. 配置Maven从私服下载构件

    --------------------siwuxie095                                     配置 Maven 从私服下载构件         从 Nexus ...

  2. 【校招面试 之 网络】第1题 TCP和UDP

    TCP UDP1.TCP与UDP基本区别  (1)基于连接与无连接  (2)TCP要求系统资源较多,UDP较少:   (3)UDP程序结构较简单(头只有8个字节:源端口号.目标端口号.长度.差错)   ...

  3. 【校招面试 之 C/C++】第1题 为什么优先使用构造函数的初始化列表

    1.首先看一个例子: #include<iostream> using namespace std; class Test1 { public: Test1() // 无参构造函数 { c ...

  4. OOP的几个不常用的方法

    from OOP_多态 import cat c = cat("cat") print(c.__doc__) print(cat.__doc__) # # 打印类的描述信息,也就是 ...

  5. Spring框架的事务管理之声明式事务管理的类型

    1. 声明式事务管理又分成两种方式 * 基于AspectJ的XML方式(重点掌握)(具体内容见“https://www.cnblogs.com/wyhluckdog/p/10137712.html”) ...

  6. WebApi是轻量级的,WCF是重量级的,可以Api调用WCF,更灵活

    WCF.WebAPI.WCFREST.WebService之间的区别 注明:转载 在.net平台下,有大量的技术让你创建一个HTTP服务,像Web Service,WCF,现在又出了Web API.在 ...

  7. Byte字节与位

    位(bit)字节(byte)一字节是8位所以2Byte是16位二进制

  8. 第十届Mockplus ▪ UXPA用户体验西南赛区决赛成功举行

    九月的重庆,秋意渐浓. 伴随着凉爽的秋风,第十届Mockplus·UXPA国际用户体验创新大赛(UXD Award2018)西南赛区决赛于9月16日下午在四川美术学院-虎溪校区成功举办.来自西南区域各 ...

  9. 《JavaScript高级程序设计》笔记

    1. 当在函数内部定义了其他函数时,就创建了闭包.闭包有权访问包含函数内部的所有变量. 2. 闭包可以分隔变量空间,不会占用全局空间而造成相互间的干拢.使用闭包可以在JavaScript中模仿块级作用 ...

  10. 主频3.0 1g内存是什么意思

    我会讲解一些常用的计算机应用知识.希望大家多多支持,稍后更新,我的技术水平在国内属于顶尖的水平,不服来战...稍后更新...