SQL2005 学记笔记(10)

一 事务
1 为什么需要事务
我们先来看一个案例,下面为一个银行系统
1)判断是bank数据库是否已有表bank,如果有则删,无则建
use bank
go
if exists(select * from sysobjects where name='bank')
  drop table bank
go
create table bank
(
 customername char(10),
 currentmoney money
)
go

2)对currentmoney创建 check约束,即存额不能小于1,因有两人开帐户存款,故insert两条记录.

alter table bank
 add constraint ck_currentmoney check(currentmoney>=1)
go
insert into bank(customername,currentmoney) values('张三',1000)
insert into bank(customername,currentmoney) values('李四',1)
select * from bank
go

3)现在张三要转1000给李四,系统作update操作

use bank
go
update bank set currentmoney=currentmoney-1000
       where customername='张三'
update bank set currentmoney=currentmoney+1000
       where customername='李四'
go
select * from bank
----------------运行结果如下---------
消息 547,级别 16,状态 0,第 1 行
UPDATE 语句与 CHECK 约束"ck_currentmoney"冲突。该冲突发生于数据库"bank",表"dbo.bank", column 'currentmoney'。
语句已终止。

(1 行受影响)
customername currentmoney
------------ ---------------------
张三           1000.00
李四           1001.00
-------------------------------------------

update后,我们发现,张三的1000没有少,但李四的却被加了1000,变为1001了,这样银行就无缘无故的要多支付1000了,这肯定不行。
为什么会出现这样的问题呢?
我们来看一下,转帐前数据,张三:1000  李四:1 ,并对金额建立了check约束,金额要>=1,  但由于转帐后,张三的金额将变为0(1000-1000),这不符合我们设定的check约束,故出错,使得张三减1000的操作失败。
而张四加1000的操作却成功了,故才产生如上面数据的结果。

那如何才能避免这种错误的发现呢?可不可以做到当张三update出错时,后面的相关操作都失效呢?答案是可以的。

这就要用到今天我们要学习的,事务。


 2 什么是事务
  事务(transaction)是单个的工作单元。如果某一事物成功,则在该事务中进行的所有数据更改均会提交,如果事务遇到错误则所有数据更改被清除,事务是一种机制,一个操作序列,它包含了一组数据库操作命令,并且所有的命令作为一个整体一起向系统提交或撤销操作请求,即这一组数据库命令要么都执行,要么都不执行,因此事务是一个不可分割的工作逻辑单元,在数据库系统上执行并发操作时事务是作为最小的控制单元来使用的。
使用下面的Sql语句管理事务
 开始事务:begin transaction
 提交事务:commit transaction
 撤销事务:rollback transaction


使用全局变量@@error来判断sql 语句是否出错,如果出错则@@error为非零值。

好,我们用“事务”来重新完成上例。
基本思路,运用全局变量@@error来判断执行过程中是否有误,若有则利用“事务”的rollback transaction来撤销事务,使得这个事务停止并撤销该事务所有操作,所有数据更改被清除。

use bank
go
select * from bank
go
begin transaction /# 开始这个事务 #/
declare @errorsum int
set @errorsum=0 /# 用于累计错误值 #/
update bank set currentmoney=currentmoney-1000
       where customername='张三'
set @errorsum=@errorsum+@@error /# 把错误值赋予这个变量 #/
update bank set currentmoney=curremtmoney+1000
       where customername='李四'
set @errorsum=@errorsum+@@error /# 把错误值赋予这个变量 #/
 if @errorsum<>0  /# 判断执行上面操作时是否有发现错误 #/
  begin
    rollback transaction /# 有错误发现,则撤消从begin transaction后到此的的所有操作 #/
   end
else
  begin
    commit transaction /# 没有错误,则把上面的操作全部一起提交#/
  end
go
select * from bank
go

我们执行发现,由于有错误发发,转帐操作被辙消,转帐不成功,这正是我们要的效果。
------------------执行情况如下---------------
customername currentmoney
------------ ---------------------
张三           1000.00
李四           1.00

(2 行受影响)

消息 207,级别 16,状态 1,第 7 行
列名 'curremtmoney' 无效。
customername currentmoney
------------ ---------------------
张三           1000.00
李四           1.00

(2 行受影响)

-------------------------------------------
我们发现,因为转帐失败,存款没有变化。

你可能感兴趣的:(sql,sql,数据库,server,笔记,休闲)