版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/marko_zheng/article/details/86015621
SQL SERVER 事务和锁
事务:保持逻辑数据一致性与可恢复性,必不可少的利器。
锁:多用户访问同一数据库资源时,对访问的先后次序权限管理的一种机制,没有他事务或许将会一塌糊涂,不能保证数据的安全正确读写。
/*******************************************************************************************************************************/
先举一个典型的业务
A给B转账100元
在数据库中 实际进行了两步操作
- A的账户减掉100元
- B的账户增加100元
这两个动作应当构成一个不可分割的整体,要么完成其中的所有动作,要么不执行其中任何动作
这两个动作就是一种“不可分割”的业务单 位 。一旦某个环节失败,就需要回滚(恢复到初始状态)
/*******************************************************************************************************************************/
事务的特性
- 原子性:事务必须是一个自动工作的单元,要么全部执行,要么全部不执行。
- 一致性:事务结束的时候,所有的内部数据都是正确的。
- 隔离性:并发多个事务时,各个事务不干涉内部数据,处理的都是另外一个事务处理之前或之后的数据。
- 持续性:事务提交之后,数据是永久性的,不可再回滚。
事务的常用语句
Begin Transaction:标记事务开始。
Commit Transaction:事务已经成功执行,数据已经处理妥当。
Rollback Transaction:数据处理过程中出错,回滚到没有处理之前的数据状态,或回滚到事务内部的保存点。
Save Transaction:事务内部设置的保存点,就是事务可以不全部回滚,只回滚到这里,保证事务内部不出错的前提下。
创建一个事务 把id为6的stu_id改为2014100766,stu_math改成100,id值不存在于表中,则事务回滚,不执行
--创建一个事务 把id为6的stu_id改为2014100766
begin tran test_tran
update stu set stu_id = concat(201410076,stu_id) where id = 6
update stu set stu_math=100 where id = 6
if @@ERROR!=0
rollback transaction
else
commit tran test_tran
用try catch再写一遍
--try catch 再写一遍
begin tran test_tran2
begin try
--把id为7的stu_id改为201410076
update stu set stu_id = concat(201410076,stu_id) where id = 7
end try
begin catch
select Error_number() as ErrorNumber, --错误代码
Error_severity() as ErrorSeverity, --错误严重级别,级别小于10 try catch 捕获不到
Error_state() as ErrorState , --错误状态码
Error_Procedure() as ErrorProcedure , --出现错误的存储过程或触发器的名称。
Error_line() as ErrorLine, --发生错误的行号
Error_message() as ErrorMessage --错误的具体信息
if(@@trancount>0) --全局变量@@trancount,事务开启此值+1,他用来判断是有开启事务
rollback tran ---由于出错,这里回滚到开始,第一条语句也没有插入成功。
end catch
if(@@trancount>0)
commit tran test_tran2
/------------------------------------------------01-08------------------------------------
写一个存储过程,根据传入的参数,修改学生成绩,姓名
-- 创建一个修改学生信息和成绩的存储过程
go
create procedure test_tran_procedure
@id varchar(200)='',
@stu_id varchar(200)='',--学生stu_id
@stu_name varchar(200)='',--姓名
@stu_chinese varchar(200)='', --语文
@stu_math varchar(200)='',--数学
@stu_english varchar(200)='', --英语
@stu_total varchar(200)='' --总成绩
as
begin tran
begin try
--执行语句
if(@id = '')
print '警告信息:id请勿为空';
rollback tran --如果id 不传 语句不执行
if(@stu_id!='')
update stu set stu_id = @stu_id where id = @id --用户传入stuid 则修改stu_id
if(@stu_name!='')
update stu set stu_name = @stu_name where id = @id
if(@stu_chinese!='')
update stu set stu_chinese = @stu_chinese where id = @id
if(@stu_math!='')
update stu set stu_math = @stu_math where id = @id
if(@stu_english!='')
update stu set stu_english = @stu_english where id = @id
if(@stu_total!='')
update stu set stu_total = @stu_total where id = @id
--如果不传参数,事务回滚
end try
begin catch
select Error_number() as ErrorNumber, --错误代码
Error_severity() as ErrorSeverity, --错误严重级别,级别小于10 try catch 捕获不到
Error_state() as ErrorState , --错误状态码
Error_Procedure() as ErrorProcedure , --出现错误的存储过程或触发器的名称。
Error_line() as ErrorLine, --发生错误的行号
Error_message() as ErrorMessage --错误的具体信息
if(@@trancount>0) --全局变量@@trancount,事务开启此值+1,他用来判断是有开启事务
rollback tran ---由于出错,这里回滚到开始
end catch
if(@@trancount>0)
commit tran
--调用存储过程
exec test_tran_procedure @stu_id = '1111111111';
exec test_tran_procedure @id = '6',@stu_id = '20141007123',
@stu_name='',@stu_chinese='',@stu_math='',@stu_english='',@stu_total='1001';