为什么需要事务?

使用事务保证操作数据的完整性。

我的理解是:事务是避免在操作数据库时,出现服务器宕机、断电、断网等一些问题时,来解决操作数据库的完整性!


 

示例:

银行转账问题

假定资金从账户A转到账户B,至少需要两步

1.账户A的资金减少

2.然后账户B的资金相应增加

假定张三的账户直接转账1000元到李四的账户

如果遇到,数据库操作错误就会出现下面的问题

张三的账户没有减少

但李四的账户却多了1000元

1000+1001=2001元

总额多出了1000元!

这样的问题如何解决呢?使用事务


 

什么是事务

1.事务(TRANSACTION)是作为单个逻辑工作单元执行的一系列操作

2.多个操作作为一个整体向系统提交,要么都执行、要么都不执行

3.事务是一个不可分割的工作逻辑单元

转账过程就是一个事务

它需要两条UPDATE语句来完成,这两条语句是一个整体

如果其中任一条出现错误,则整个转账业务也应取消,两个账户中的余额应恢复到原来的数据,从而确保转账前和转账后的余额不变,即都是1001元


事务的特性

事务必须具备以下四个属性,简称ACID 属性:

1.原子性(Atomicity)

事务是一个完整的操作,事务的各步操作是不可分的(原子的),要么都执行,要么都不执行

2.一致性(Consistency)

当事务完成时,数据必须处于一致状态

3.隔离性(Isolation)

并发事务之间彼此隔离、独立,它不应以任何方式依赖于或影响其他事务

4.永久性(Durability)

事务完成后,它对数据库的修改被永久保持

 


 

如何创建事务

使用SQL语句管理事务

一.开始事务



BEGIN TRANSACTION



二.提交事务



COMMIT TRANSACTION



三.回滚(撤销)事务



ROLLBACK TRANSACTION



一旦事务提交或回滚,则事务结束

判断某条语句执行是否出错:

使用全局变量@@ERROR

@@ERROR只判断当前一条T-SQL语句执行是否有错

为了判断事务中所有T-SQL语句是否有错,可以对错误进行累计



SET @errorSum=@errorSum+@@ERROR



事务可以嵌套


事务分类

显式事务

用BEGIN TRANSACTION明确指定事务的开始

最常用的事务类型

隐性事务 implicit_transctions on

1.通过设置SET IMPLICIT_TRANSACTIONS ON

2.其后的T-SQL语句自动启动一个新事务

3.提交或回滚一个事务后,下一个 T-SQL 语句又将启动一个新事务

自动提交事务

SQL Server 的默认模式

每条单独的 T-SQL 语句视为一个事务


 

示例

从张三的账户转出1000元,存入李四的账户中



BEGIN TRANSACTION 
/*--定义变量,用于累计事务执行过程中的错误--*/
DECLARE @errorSum INT 
SET @errorSum=0                                             --初始化为0,即无错误
/*--转账:张三的账户减少1000元,李四的账户增加1000元*/
UPDATE bank SET currentMoney = currentMoney - 1000
   WHERE customerName = '张三'
SET @errorSum = @errorSum + @@ERROR --累计是否有错误
UPDATE bank SET currentMoney = currentMoney + 1000
   WHERE customerName = '李四'
SET @errorSum = @errorSum + @@ERROR



BEGIN TRANSACTION

开始事务(指定事务从此处开始,后续的T-SQL语句都是一个整体)

SET @errorSum = @errorSum + @@ERROR

累计是否有错误



IF @errorSum<>0  --如果SQL语句执行出错
  BEGIN
    PRINT '交易失败,回滚事务'
    ROLLBACK TRANSACTION 
  END  
ELSE
  BEGIN
    PRINT '交易成功,提交事务,写入硬盘,永久的保存'
    COMMIT TRANSACTION   
  END
GO
PRINT '查看转账事务后的余额'
SELECT * FROM bank  
GO



根据执行是否有错误,决定提交事务,或撤销事务

如果有错,则回滚操作,事务结束

如果成功,则提交操作,事务结束

 

sql server 查看事务默认级别 sql server的事务_数据结构与算法

sql server 查看事务默认级别 sql server的事务_数据库_02


 

使用显式事务完成批量插入10个学生考试成绩的操作

使用全局变量@@ERROR判断插入操作是否成功

使用IF语句判断@@ERROR值。如果插入成功,提交事务;否则回滚事务



BEGIN TRANSACTION
DECLARE @errorSum INT
SET @errorSum=0
/*--插入数据--*/
… …
INSERT INTO Result(StudentNo,SubjectNo,ExamDate,StudentResult)
            VALUES(10012,1,'2009-5-20',102)      --分数违反约束
SET @errorSum=@errorSum+@@ERROR
… …
IF(@errorSum<>0) --如果有错误
  BEGIN
    PRINT '插入失败,回滚事务'
    ROLLBACK TRANSACTION 
  END  
ELSE
  BEGIN
    PRINT '插入成功,提交事务'
    COMMIT TRANSACTION   
  END



 

需求说明: 将毕业学生的基本信息和考试成绩分别保存到历史表中

提示:

1.使用显式事务

2.查询Result表中所有Y2学生的考试成绩,保存到表HistoreResult中

3.删除Result表中所有Y2学生的考试成绩

4.查询Student表中所有Y2的学生记录,保存到表HistoryStudent中

5.删除Studet表中所有Y2学生记录



BEGIN TRANSACTION
DECLARE @errorSum INT
SET @errorSum=0
/*--查询Result表中所有Y2学生的考试成绩,保存到新表HistoreResult*/
SELECT Result.* INTO HistoreResult FROM Result INNER JOIN Student ON Result.StudentNo=Student.StudentNo
INNER JOIN Grade ON Grade.GradeId=Student.GradeId 
WHERE GradeName='Y2'
SET @errorSum=@errorSum@@ERROR
/*--删除Result表中所有Y2学生的考试成绩*/
DELETE  Result FROM  Result JOIN Student ON Result.StudentNo=Student.StudentNo
INNER JOIN Grade ON Grade.GradeId=Student.GradeId 
WHERE GradeName='Y2'
SET @errorSum=@errorSum+@@ERROR
/*--将Student表中所有Y2的学生记录,保存到新表HistoryStudent*/
… …
/*--删除Studet表中所有Y2学生记录*/
… …
/*--根据是否有错误,确定事务是提交还是撤销--*/



 

 


 

笔记



--银行转账业务
--角色:张三、李四   功能:张三扣100  李四加100

--张三扣100
declare @money money=100
update bank 
set usermoney=usermoney-@money
where name='张三' --数据库不支持+= -=
update bank 
set usermoney=usermoney+@money
where name='李四' --数据库不支持+= -=
--不合理  两条语句不是一个整体
--数据库三种事务
--insert添加  delete 删除  update 修改     select查询(不会影响数据)
--第一种:显示事务
--系统函数:捕获T-SQL语句执行的错误编号@@error
begin transaction  --开始事务
declare @money money=100
declare @sumError int=0--默认无错
update bank 
set usermoney=usermoney-@money
where name='张三'  
set @sumError=@sumError+@@error
update bank 
set usermoney=usermoney+@money
where name='李四'  
set @sumError=@sumError+@@error

if @sumError=0
begin
    print '转账成功,提交';--分号代表一条语句的结束
    commit transaction --提交事务
end
else
begin
    print '转账失败,回滚'+cast(@sumError as varchar) 
    rollback transaction --回滚事务
end
 
--第二种:自动事务commit提交
--第三种:隐式事务
SET IMPLICIT_TRANSACTIONS off --打开隐式事务 cmd
--如果打开隐式事务,使用操作数据语句 事务锁表
--正在等待下一步指令
--提交 commit(提交:执行操作),手动提交一种,关闭当前回话也会提交
--取消 rollback(回滚:取消操作)
commit
rollback 
--oracle 数据库 默认隐式事务开启,sqlserver默认隐式事务关闭
--sqlconnection 连接对象 conn.close()

--sqlserver2014工具 服务
--如果和金融相关数据结构 数据还原