曲演杂坛--使用TRY CATCH应该注意的一个小细节
群里一个朋友遇到一个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应该注意的一个小细节的更多相关文章
- 曲演杂坛--一条DELETE引发的思考
原文:曲演杂坛--一条DELETE引发的思考 场景介绍: 我们有一张表,专门用来生成自增ID供业务使用,表结构如下: CREATE TABLE TB001 ( ID ,) PRIMARY KEY, D ...
- 曲演杂坛--蛋疼的ROW_NUMBER函数
使用ROW_NUMBER来分页几乎是家喻户晓的东东了,而且这东西简单易用,简直就是程序员居家必备之杀器,然而ROW_NUMBER也不是一招吃遍天下鲜的无敌BUG般存在,最近就遇到几个小问题,拿出来供大 ...
- 曲演杂坛--当ROW_NUMBER遇到TOP
值班期间研发同事打来电话,说应用有超时,上服务器上检查发现有SQL大批量地执行,该SQL消耗IO资源较多,导致服务器存在IO瓶颈,细看SQL,发现自己都被整蒙了,不知道这SQL是要干啥,处理完问题赶紧 ...
- 曲演杂坛--特殊字符/生僻字与varchar
对于中文版的SQL SERVER,默认安装后使用的默认排序规则为Chinese_PRC_CI_AS,在此排序规则下,使用varchar类型来可以“正常存取”存放中文字符以及一些东南亚国家的字符,同时v ...
- 曲演杂坛--使用CTE时踩的小坑:No Join Predicate
在一次系统优化中,意外发现一个比较“坑”的SQL,拿出来供大家分享. 生成演示数据: --====================================== --检查测试表是否存在 IF(O ...
- 曲演杂坛--为什么SELECT语句会被其他SELECT阻塞?
很多刚入门的DBA在捕获阻塞得时候,会问这么一个问题“为什么这个SELECT语句被那个SELECT语句阻塞了,难道不是共享锁么?” 让我们来做个小测试,首先准备一些测试数据: --========== ...
- 曲演杂坛--EXISTS语句
通常在我写EXISTS语句时,我会写成IF EXISTS(SELECT TOP(1) 1 FROM XXX),也没细细考究过为什么要这么写,只是隐约认为这样写没有啥问题,那今天就深究下吧! 首先准备测 ...
- 曲演杂坛--SQLCMD下执行命令失败但没有任何错误提示的坑
今天使用SQLCMD导入到SQL SERVER数据库中,看着数据文件都成功执行,但是意外发现有一个文件数据没有成功导入,但执行不报错,很容易导致问题被忽略. 使用存在问题的文件做下测试,从界面上看几行 ...
- 曲演杂坛--Update的小测试
今天偶然想起一个UPDATE相关的小问题,正常情况下,如果我们将UPDATE改写成与之对应的SELECT语句,其SELECT查询结果应与UPDATE的目标表存在一对一的关系,例如: 对于UPDATE语 ...
随机推荐
- Windows XP with SP3大客户免激活日文版
原贴地址:http://www.humin.com.cn/ja_windows_xp_professional_with_service_pack_3_x86_dvd_vl_x14-74058-iso ...
- 'org.springframework.beans.factory.xml.XmlBeanFactory' is deprecated
'org.springframework.beans.factory.xml.XmlBeanFactory' is deprecated XmlBeanFactory这个类已经被摒弃了.可以用以下代替 ...
- Partition List双色问题链表版
[抄题]: Given a linked list and a value x, partition it such that all nodes less than x come before no ...
- Visual Event查看页面相关绑定事件
页面相关绑定的事件比较复杂,在不熟悉的情况下很难找到相关逻辑的位置,所以希望借助工具来帮自己理清相关事件的脉络走向. 浏览器 工具 chrome( 58.0.3029.110) Visual Even ...
- dede 复制文章,远程图片无法本地化
解决方法: 1.找到dede的后台目录,在后台目录下的inc下找到inc_archives_functions.php 2.搜索GetCurContent函数,找到如下这段代码: preg_match ...
- SqlServer中批量update
现在我有两张表分别是S_PERSON,S_USER S_PERSON S_USER 我现在想把S_USER表中的ACCOUNT批量修改成S_PERSON的ACCOUNT 我们可以发现S_USER表中有 ...
- Golang之go 命令用法
Go 命令 Go 命令 Go语言自带有一套完整的命令操作工具,你可以通过在命令行中执行go来查看它们: 图1.3 Go命令显示详细的信息 这些命令对于我们平时编写的代码非常有用,接下来就让我们了解一些 ...
- pkg_config找不到库
解决方法 假设libavutil默认安装时libavutil.pc安装到了 /usr/lib64/lib/pkgconfig/ 中,而 echo $PKG_CONFIG_PATH 结果中没有这个路径, ...
- Core Dump 程序故障分析
1.编写一个应用程序,使用gdb+core dump进行故障分析, core dump的概念: core dump又叫核心转存:当程序在运行过程中发生异常,这时Linux系统可以把程序在运行时的内存内 ...
- 如果程序集是从 Web 上下载的,即使它存储于本地计算机,Windows 也会将其标记为 Web 文件,http://go.microsoft.com/fwlink/?LinkId=179545
使用Silverlight,经常弄出很多莫名的XXX文件来于Web,神马信任程序集,就Build个程序都那么麻烦,应该在所有发布时注明一些最基本的配置说明,最BT莫过于连下载程序集的地方都找不到. 若 ...