事务详解
什么是事务
以后我们系统可能实现一个功能,可能不止操作一张表,比如有多张表。最简单的是汇总表和明细表,比如订单表和订单明细,这是一种一对多的关系。比如添加一条订单,可能就会添加十条明细。如果没有事务,假设添加订单成功,但明细只添加了5条,就会导致数据不正确。
事务:保持逻辑数据一致性与可恢复性,要么全部执行,要么全部不执行,回到原数据状态。
书面解释:事务具有原子性、一致性、隔离性、持久性。
- 原子性:事务必须是一个自动工作的单元,要么全部执行,要么全部不执行。
- 一致性:事务结束的时候,所有的内部数据都是正确的。
- 隔离性:并发多个事务时,各个事务不干涉内部数据,处理的都是另外一个事务处理之前或之后的数据。
- 持久性:事务提交之后,数据是永久性的,不可再回滚。
SQL Server 中事务的三种类型
- 自动提交事务:SQL Server 默认的事务模式,每条 Sql 语句都被看成一个事务进行处理。
- 显式事务:T-SQL 标明,由
Begin Transaction开启事务开始,由Commit Transaction提交事务、Rollback Transaction回滚事务结束。 - 隐式事务:使用
Set IMPLICIT_TRANSACTIONS ON将隐式事务模式打开,不用Begin Transaction开启事务,当一个事务结束,这个模式会自动启用下一个事务,只用Commit Transaction提交事务、Rollback Transaction回滚事务即可。
不使用事务的情况
-- 清空表数据
delete from guest
-- 插入三条记录
INSERT INTO [dbo].[Guest]([name],[age],[createtime]) VALUES('张一',1,GETDATE()) -- 正确
INSERT INTO [dbo].[Guest]([name],[age],[createtime]) VALUES('张二','二',GETDATE()) -- 错误,下面的脚本不会执行
INSERT INTO [dbo].[Guest]([name],[age],[createtime]) VALUES('张三',3,GETDATE()) -- 正确
-- 查找
select * from guestCode language: JavaScript (javascript)
使用事务的例子(有错误时回滚)
-- 清空表数据
delete from guest
-- 插入三条记录
begin tran -- 开启事务
begin try
INSERT INTO [dbo].[Guest]([name],[age],[createtime]) VALUES('张一',1,GETDATE()) -- 正确
INSERT INTO [dbo].[Guest]([name],[age],[createtime]) VALUES('张二','二',GETDATE()) -- 错误,下面的脚本不会执行
INSERT INTO [dbo].[Guest]([name],[age],[createtime]) VALUES('张三',3,GETDATE()) -- 正确
end try
begin catch
-- 出错就会到达这里
-- 执行失败 输出错误信息
select Error_number() as ErrorNumber, -- 错误代码
Error_severity() as ErrorSeverity, -- 错误严重级别
Error_state() as ErrorState , -- 错误状态码
Error_Procedure() as ErrorProcedure , -- 出现错误的存储过程或触发器的名称
Error_line() as ErrorLine, -- 发生错误的行号
Error_message() as ErrorMessage -- 错误的具体信息
-- 因为出错了,恢复数据,回滚事务
if(@@TRANCOUNT>0)
rollback tran
end catch
if(@@TRANCOUNT>0)
commit tran
-- 查找
select * from guestCode language: JavaScript (javascript)
所有都成功的情况
-- 清空表数据
delete from guest
-- 插入三条记录
begin tran -- 开启事务
begin try
INSERT INTO [dbo].[Guest]([name],[age],[createtime]) VALUES('张一',1,GETDATE()) -- 正确
INSERT INTO [dbo].[Guest]([name],[age],[createtime]) VALUES('张二',2,GETDATE()) -- 正确
INSERT INTO [dbo].[Guest]([name],[age],[createtime]) VALUES('张三',3,GETDATE()) -- 正确
end try
begin catch
-- 出错就会到达这里
if(@@TRANCOUNT>0)
rollback tran
end catch
if(@@TRANCOUNT>0)
commit tran
-- 查找
select * from guestCode language: JavaScript (javascript)
Previous: IF、WHILE 与变量
Next: 组合主键