使用中经常用到@@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  相关附件

相关SQL脚本

@@Error使用简单小结的更多相关文章

  1. 前台vue的使用简单小结

    前台vue的使用简单小结 本项目要求:安装有node.js 6.0以及以上安装npm使用vue.js官方安装方法初始化项目npm install安装VueResurce:npm install vue ...

  2. springboot微服务的简单小结

    springboot微服务的简单小结 近来公司用springboot微服务,所以小结一下. 基础: 什么是SpingBoot微服务? 如何创建SpringBoot微服务? 如何管理和完善SpringB ...

  3. ASP.NET MVC ViewData/ViewBag 简单小结

    近期在项目中遇到一个问题,就是用ViewBag.Model存储匿名对象传递给View,但是需要根据条件给匿名对象添加属性,这个可真心不易,Google了一下发现很多方案都是动态编译神马的,感觉好高大上 ...

  4. git知识简单小结

    git特点: 1)分布式 2)存储快照而非差异 3)本地有完全的版本库,几乎所有操作都在本地 4)有内在的一致性,SHA1 5)优秀的分支管理 6)支持各种协同模式 7)开源,有一些第三方软件可整合使 ...

  5. SpringMVC_简单小结

    SpringMVC是一个简单的.优秀的框架.应了那句话简单就是美,而且他强大不失灵活,性能也很优秀. 机制:spring mvc的入口是servlet,而struts2是filter(这里要指出,fi ...

  6. log4c 编译安装简单小结(ubuntu12)

    1 下载源码,解压 (假定解压到了当前用户的根目录下,位置是~/log4c-1.2.3) 2 编译安装log4c(指定--prefix极其重要,如果没有指定到/usr下会有一堆麻烦事,还有,不能按照他 ...

  7. 微信小程序支付简单小结与梳理

    前言 公司最近在做微信小程序,被分配到做支付这一块,现在对这一块做一个简单的总结和梳理. 支付,对于购物来说,可以说是占据了十分重要的一块,毕竟能收到钱才是重点. 当然在开发之前,我们需要有下面这些东 ...

  8. 关于Python中的ifelse、while和for循环的简单小结

    1.ifelse 1.1首先简单编辑一个关于ifelse的程序: _username = 'yanfeixu' _password = 'wuyifan' username = input(" ...

  9. java post请求的表单提交和json提交简单小结

    在java实现http请求时有分为多种参数的传递方式,以下给出通过form表单提交和json提交的参数传递方式: public String POST_FORM(String url, Map< ...

随机推荐

  1. 四月二十五日,bugzilla for CentOS 安装

    Bugzilla for CentOS 5.4 制作人,陈浩 时间:2014.4.25 原创 文件夹 Bugzilla for CentOS 5.4 一. 装系统 1) 新建虚拟机  15G硬盘,51 ...

  2. cdoj 04 Complete Building the Houses 暴力

    Complete Building the Houses Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/# ...

  3. 【转】Delphi多线程学习(9):多线程数据库查询(ADO)

    原文:http://www.cnblogs.com/djcsch2001/articles/2382559.html ADO多线程数据库查询通常会出现3个问题: 1.CoInitialize 没有调用 ...

  4. [Angular 2] Share a Service Across Angular 2 Components and Modules

    Services are used to share data between components. They follow a module pattern that allows you to ...

  5. 【UML】具体解释六种关系

    UML中包括六中关系.各自是:关联(Association).聚合(Aggregation).组合(Composition).泛化(Generalization).依赖(Dependency).实现( ...

  6. PHP __autoload函数(自动载入类文件)的使用方法(转)

    详细出处参考:http://www.jb51.net/article/29625.htm 在使用PHP的OO模式开发系统时,通常大家习惯上将每个类的实现都存放在一个单独的文件里,这样会很容易实现对类进 ...

  7. 对javascript this的理解

    对于this的理解,大部分时间都比较模糊,最近几天做了一些研究,记录一下 首先应该明白,this是执行上下文的一个属性,它的值取决于执行上下文,执行上下文和函数调用方式相关,定义一个function的 ...

  8. Photoshop-制作图片圆角2种方法[转]

    方案一:       使用选区和蒙版相结合,用图章制作圆角选区,删除多余部分 效果: 实现步骤: 一.如果是直接在已有的图片上面编辑则看下图,否则跳过此不 二.用矩形工具选择需要保留的图片内容 三.选 ...

  9. 基于css3的文字3D翻转特效

    一款基于css3的文字3D翻转特效.这款特效当鼠标经过文字的时候3D翻转显示阴影.效果图如下: 在线预览   源码下载 实现的代码. html代码: <div class="compo ...

  10. Oracle—用户管理的完全恢复(四)

    在用户管理的备份(三)中,最后打开数据库时,用了alter database open resetlogs;的命令,这里为什么用resetlogs命令? 一.resetlogs的作用 1.将当前的日志 ...