一、有时候我们需要同时执行很多个SQL操作,但是这些要执行的SQL有一部分执行成功了,比如原本应该向几个相互关联的表中插入数据,但是只有其中一个表的数据插入成功了,这时按照正常的逻辑,只要插入其中一个表失败了,那么就应该撤销已经成功了插入操作,这样事务就派上用场了。
二、事务的特性
1、原子性 事务是一个完整的操作,事务的各操作时不可分的,要么都执行,要么都不执行。
2、一致性 当事务完成时,数据必须处于一致状态
3、隔离性 并发事务之间彼此隔离,独立,它不应该以任何方式依赖与或影响其他事务。
4、永久性 事务完成后,它对数据库的修改会永久行的保存。、
三、事务的三个步骤
开启事务
BEGIN TRANSACTION
这里是要执行的SQL脚本
if 判断SQL脚本是否产生错误
如果执行SQL脚本没有出错,那么就执行
COMMIT TRANSACTION
else
如果执行SQL脚本出错,那么就回滚事务
ROLLBACK TRANSACTION
具体代码如下:
DECLARE @errorSum int --定义变量,用于累计事务执行中的错误 set @errorSum = 0; --0代表无错误 --开启事务 begin transaction begin --SQL操作 --如果SQL语句发生错误,那么就让错误变量++ set @errorSum = @errorSum + @@ERROR;--@@ERROR 是一个全局变量,只要发生执行SQL语句错误时,@@ERROR就会自动+1 if(@errorSum>0) --有错误就回滚事务 rollback transaction else --没有错误就提交事务 commit transaction end go
三、事务的应用(在SQLserver中事务通常会结合存储过程一起使用)
这里举一个简单的例子:如图是一个简单的表,我会写一个存储过程,在存储过程中向表中插入两条数据,第一条会插入成功,但是第二条会出错,出错之后事务就会回滚,让第一条插入SQL也失败。
use testdb; go if exists(select * from sysobjects where name ='testtransaction') drop procedure testtransaction go create procedure testtransaction @_user nchar(20), @_pwd nchar(20), @score decimal(6,2) as declare @error_count int set @error_count=0;--用于记录错误信息的条数 begin begin begin transaction begin insert into userTable(_user,_pwd,score) values('贺兰婷','love123',111);--这一条SQL会成功 insert into userTable(_user,_pwd,score) values(@_user,@_pwd,@score);--这一条SQL需要在外部调用存储过程时传递参数 --手动让错误条数加1,然后下面事务就会回滚 set @error_count = @error_count +1; set @error_count = @error_count + @@ERROR;--内部变量@@ERROR 这个表示如果上一条SQL语句出错,那么这一条SQL语句就会执行,错误信息条数就会增加1 if @error_count >0 --如果错误信息条数大于0 证明在执行SQL的过程中出现了错误,则应当让事务回滚 begin print('插入失败!'); rollback transaction end else begin print('插入成功!'); commit transaction end end end end;
下面我们调用一下这个存储过程
begin exec testtransaction '你好','你好呀!',8908; end
执行结果如下:
当插入失败时事务会自动回滚到初始状态,也就是说,我们插入成功的两条数据会失败!