@@Error使用简单小结
使用中经常用到@@Error来判断上一个语句是否执行成功,对此小结一下,可能有些不准确,欢迎指出。
1.1 介绍
SQL SERVER 中@@表示系统全局变量
(1) 返回执行的上一个 Transact-SQL 语句的错误号,如果执行没有错误,则返回 0 。
(2) 如果错误是 sys.messages 目录视图中的错误之一,则 @@ERROR 将包含 sys.messages.message_id 列中表示该错误的值。 可以在 sys.messages 中查看与 @@ERROR 错误号相关的文本信息。
(3) 由于 @@ERROR 在每一条语句执行后被清除并且重置,因此应在语句验证后立即查看它,或将其保存到一个局部变量中以备以后查看。
1.2 范例及使用
(1) 分析执行SQL出现错误,后续脚本的执行情况
执行语句:
UPDATE tbOrder SET OrderNo = '201605010008' WHERE OrderNo = '201605010001'
--执行上一步出现外键约束错误,并且继续执行下一步(547为约束错误)
PRINT @@ERROR --输出错误号
UPDATE tbOrder SET OrderAmount = 'ABC' WHERE OrderNo = '201605010001'
--在执行上一步时出现类型异常,并且不执行下面的步骤
PRINT @@ERROR --未输出
说明:第1个SQL出错后,仍然执行了后面的代码,输出了@@Error错误号,第2个SQL出错后直接终止后续执行。
说明执行SQL出现错误后,有的错误会直接终止后续执行,有的出现错误后仍然可以继续执行后续脚本
(2) 查询成功后,系统变量@@Error变为0
执行语句:
DELETE FROM tbOrder WHERE OrderNo = '201605010001'
PRINT 'Delete: ' + CAST(@@ERROR AS VARCHAR(20)) --输出
SELECT 1
PRINT 'Select: ' + + CAST(@@ERROR AS VARCHAR(20)) --输出 Select:0
说明:执行SQL 成功后,@@Error参数被设置为0
(3) 通过Try Catch捕获错误,输出@@Error
a) 还是上面的删除操作,产生外键约束问题
执行语句:
BEGIN TRY
DELETE FROM tbOrder WHERE OrderNo = '201605010001'
PRINT 'DELETE ' + CAST(@@ERROR AS VARCHAR(20)) --没有输出
END TRY
BEGIN CATCH
PRINT 'CATCH ' + CAST(@@ERROR AS VARCHAR(20))
PRINT ERROR_MESSAGE()
PRINT ERROR_SEVERITY()
PRINT ERROR_STATE()
END CATCH
GO
输出结果:
b) 还是上面的更新操作,产生错误,不执行后续代码
执行语句:
BEGIN TRY
UPDATE tbOrder SET OrderAmount = 'ABC' WHERE OrderNo = '201605010001'
PRINT 'UPDATE ' + CAST(@@ERROR AS VARCHAR(20))
END TRY
BEGIN CATCH
PRINT 'CATCH ' + CAST(@@ERROR AS VARCHAR(20))
PRINT ERROR_MESSAGE()
PRINT ERROR_SEVERITY()
PRINT ERROR_STATE()
END CATCH
GO
输出结果:
说明:在Try中执行SQL产生错误后,直接被Catch捕获,Try中后续代码终止执行,直接执行Catch中的代码
(4) 测试有事物的操作是否产生错误后都回滚
a) 直接增加事物
执行脚本:
BEGIN TRAN
--执行正常
INSERT INTO dbo.tbOrderDetail( OrderNo, ProductID, Quantity, Price )
VALUES ( '201605010001',50,200,10)
--执行报错
DELETE FROM tbOrder WHERE OrderNo = '201605010001'
PRINT 'DELETE: ' + CAST(@@ERROR AS VARCHAR(20))
COMMIT TRAN
执行结果(同时查询订单明细):
说明:执行出错后,前面执行的插入操作数据并没有回滚,说明直接增加事物并不能回滚出错前的数据
b) 增加@@Error判断执行是否成功
执行脚本:
BEGIN TRAN
--执行正常
INSERT INTO dbo.tbOrderDetail( OrderNo, ProductID, Quantity, Price )
VALUES ( '201605010001',50,200,10)
IF @@ERROR <> 0
BEGIN
ROLLBACK TRAN
RETURN
END
--执行报错
DELETE FROM tbOrder WHERE OrderNo = '201605010001'
--UPDATE tbOrder SET OrderAmount = 'ABC' WHERE OrderNo = '201605010001' --将Delete操作换成更新操作产生异常后事物也会回滚
IF @@ERROR <> 0
BEGIN
ROLLBACK TRAN
RETURN
END
COMMIT TRAN
执行结果(同时查询订单明细):
说明:增加@@Error判断,执行错误时前面的数据都回滚了。同时将语句中的Delete操作换成执行已屏蔽的更新操作产生异常后,事物同样也会回滚
(5) 通过设置XACT_ABORT,测试出现错误整个事物是否回滚
备注:当 SET XACT_ABORT 为 ON 时,如果执行 Transact-SQL 语句产生运行时错误,则整个事务将终止并回滚。
当 SET XACT_ABORT 为 OFF 时,有时只回滚产生错误的 Transact-SQL 语句,而事务将继续进行处理。如果错误很严重,那么即使 SET XACT_ABORT 为 OFF,也可能回滚整个事务。OFF 是默认设置。
a) XACT_ABORT 为 OFF,只有执行出错的回滚
执行脚本:
SET XACT_ABORT OFF
BEGIN TRAN
--执行正常
INSERT INTO dbo.tbOrderDetail( OrderNo, ProductID, Quantity, Price )
VALUES ( '201605010001',50,200,10)
--执行报错
DELETE FROM tbOrder WHERE OrderNo = '201605010001'
PRINT 'DELETE: ' + CAST(@@ERROR AS VARCHAR(20))
--执行正常
INSERT INTO dbo.tbOrderDetail( OrderNo, ProductID, Quantity, Price )
VALUES ( '201605010001',51,10,100)
COMMIT TRAN
执行结果(同时查询明细):
b) XACT_ABORT 为 ON,强制整个事物回滚
执行脚本:
SET XACT_ABORT ON
BEGIN TRAN
--执行正常
INSERT INTO dbo.tbOrderDetail( OrderNo, ProductID, Quantity, Price )
VALUES ( '201605010001',50,200,10)
--执行报错
DELETE FROM tbOrder WHERE OrderNo = '201605010001'
PRINT 'DELETE: ' + CAST(@@ERROR AS VARCHAR(20))
COMMIT TRAN
SET XACT_ABORT OFF
执行结果(同时查询明细):
说明:设置XACT_ABORT为OFF(默认为OFF),只有执行出错的语句回滚了,其他的没有回滚数据;设置XACT_ABORT为ON时,当执行SQL产生错误后,强制整个事物回滚,并且不在执行后续代码
(6) 通过Try Catch捕获错误,显示事物执行错误,并回滚
执行脚本:
BEGIN TRAN
BEGIN TRY
--执行正常
INSERT INTO dbo.tbOrderDetail( OrderNo, ProductID, Quantity, Price )
VALUES ( '201605010001',50,200,10)
--执行报错
DELETE FROM tbOrder WHERE OrderNo = '201605010001'
--UPDATE tbOrder SET OrderAmount = 'ABC' WHERE OrderNo = '201605010001'
COMMIT TRAN
END TRY
BEGIN CATCH
PRINT '执行错误' + CAST(@@ERROR AS VARCHAR(20))
PRINT ERROR_MESSAGE()
PRINT ERROR_SEVERITY()
PRINT ERROR_STATE()
ROLLBACK TRAN --必须增加回滚,否则事物会一直挂死在哪里
END CATCH
执行结果(同时查询订单明细):
1.3 总结说明
参照上面的使用演示及结果,可以由如下3种处理方式确保数据完整性
(1) 通过@@Error判断来语句是否执行成功,是否事物需要回滚(参见1.2 (4) )
(2) 设置XACT_ABORT为ON,强制整个事物执行出错时都回滚 (参见1.2 (5) )
(3) 通过Try Catch捕获执行异常,并回滚事物 (参见1.2 (6) )
1.4 参考资料
微软官网解释
https://msdn.microsoft.com/zh-cn/library/ms188790.aspx
try catch 捕获不到的一些错误及解决方法
http://blog.csdn.net/kk185800961/article/details/40043415
事务执行情况跟踪分析
http://blog.csdn.net/zhaowenzhong/article/details/16342843
1.5 相关附件
@@Error使用简单小结的更多相关文章
- 前台vue的使用简单小结
前台vue的使用简单小结 本项目要求:安装有node.js 6.0以及以上安装npm使用vue.js官方安装方法初始化项目npm install安装VueResurce:npm install vue ...
- springboot微服务的简单小结
springboot微服务的简单小结 近来公司用springboot微服务,所以小结一下. 基础: 什么是SpingBoot微服务? 如何创建SpringBoot微服务? 如何管理和完善SpringB ...
- ASP.NET MVC ViewData/ViewBag 简单小结
近期在项目中遇到一个问题,就是用ViewBag.Model存储匿名对象传递给View,但是需要根据条件给匿名对象添加属性,这个可真心不易,Google了一下发现很多方案都是动态编译神马的,感觉好高大上 ...
- git知识简单小结
git特点: 1)分布式 2)存储快照而非差异 3)本地有完全的版本库,几乎所有操作都在本地 4)有内在的一致性,SHA1 5)优秀的分支管理 6)支持各种协同模式 7)开源,有一些第三方软件可整合使 ...
- SpringMVC_简单小结
SpringMVC是一个简单的.优秀的框架.应了那句话简单就是美,而且他强大不失灵活,性能也很优秀. 机制:spring mvc的入口是servlet,而struts2是filter(这里要指出,fi ...
- log4c 编译安装简单小结(ubuntu12)
1 下载源码,解压 (假定解压到了当前用户的根目录下,位置是~/log4c-1.2.3) 2 编译安装log4c(指定--prefix极其重要,如果没有指定到/usr下会有一堆麻烦事,还有,不能按照他 ...
- 微信小程序支付简单小结与梳理
前言 公司最近在做微信小程序,被分配到做支付这一块,现在对这一块做一个简单的总结和梳理. 支付,对于购物来说,可以说是占据了十分重要的一块,毕竟能收到钱才是重点. 当然在开发之前,我们需要有下面这些东 ...
- 关于Python中的ifelse、while和for循环的简单小结
1.ifelse 1.1首先简单编辑一个关于ifelse的程序: _username = 'yanfeixu' _password = 'wuyifan' username = input(" ...
- java post请求的表单提交和json提交简单小结
在java实现http请求时有分为多种参数的传递方式,以下给出通过form表单提交和json提交的参数传递方式: public String POST_FORM(String url, Map< ...
随机推荐
- .git文件过大!删除大文件
在我们日常使用Git的时候,一般比较小的项目,我们可能不会注意到.git 这个文件. 其实, .git文件主要用来记录每次提交的变动,当我们的项目越来越大的时候,我们发现 .git文件越来越大. 很大 ...
- 2014年QS世界大学排名
新浪教育[微博]讯 近日2014QS世界大学排行榜发布,榜单前十强均为英美名校.其中麻省理工大学以绝对优势位居榜首:英国剑桥大学及帝国理工学院并列排名第二:哈佛大学较去年而言名次略微下降,跌至第四. ...
- Asp.Net BulletedList
BulletedList使用及详解 BulletedList是一个让你轻松在页面上显示项目符号和编号格式(Bulledted List)的控件.对于ASP.NET 1.x里要动态显示Bulledted ...
- ARM&Linux 下驱动开发第一节(小试牛刀)
#include<linux/init.h> #include<linux/module.h> static int __init hello_init(void) { pri ...
- 广州项目实施步骤I_练习安装 CentOS x64 6.4
安装Centos x64 6.4 在家里使用 Vmware10.0.1进行模拟安装. 永久KEY注册密钥:5F29M-48312-8ZDF9-A8A5K-2AM0Z 下载地址:http://pan. ...
- 【M35】让自己习惯于标准C++语言
1.最近一些年C++语言增加的特性有: a.RTTI,namespace,bool,关键字mutable和explicit,enums,以及const static int可以直接初始化. b.扩充了 ...
- [Jobdu] 题目1497:面积最大的全1子矩阵
题目描述: 在一个M * N的矩阵中,所有的元素只有0和1,从这个矩阵中找出一个面积最大的全1子矩阵,所谓最大是指元素1的个数最多. 输入: 输入可能包含多个测试样例.对于每个测试案例,输入的第一行是 ...
- 深入NGINX:我们如何设计它的性能和扩展性
为了更好地理解设计,你需要了解NGINX是如何工作的.NGINX之所以能在性能上如此优越,是由于其背后的设计.许多web服务器和应用服务器使用简单的线程的(threaded).或基于流程的 (proc ...
- script的defer和async
我们常用的script标签,有两个和性能.js文件下载执行相关的属性:defer和async defer的含义[摘自https://developer.mozilla.org/En/HTML/Elem ...
- 【KPC】关于为什么不用Zepto而用JQuery
1.zepto在window phone手机上不是很兼容 2.JQuery的Deferred对象在zepto上不支持. 3.JQuery经过压缩,以及部分页面的使用,以及缓存,可以达到优化用户体验的效 ...