事务演示--游标

---事务演示
create database TRANS_DEMO;
go

use TRANS_DEMO;
go

--银行账户表
create table BANK_ACCOUNTS
(
 ACCOUNT_NUM nvarchar(20) not null constraint PK_BANK_ACCOUNTS primary key, --帐号(主键)
 CUSTOMER_NAME nvarchar(20) not null,          --客户姓名
 BALANCE float not null              --余额
);

go

alter table BANK_ACCOUNTS add constraint CK_BANK_ACCOUNTS_BALANCE check (BALANCE >= 0 AND BALANCE <= 13000);

go

--银行业务日志表
create table BANK_TRANS_LOGS
(
 SEQ_NO bigint not null identity constraint PK_BANK_TRANS_LOGS primary key, --流水号(主键)
 ACCOUNT_NUM nvarchar(20) not null constraint FK_BANK_TRANS_LOGS_ACCOUNT_NUM_BANK_ACCOUNTS_ACCOUNT_NUM
   foreign key references BANK_ACCOUNTS(ACCOUNT_NUM),     --帐号
 AMOUNT float not null,              --金额
 DESCRIPTION nvarchar(100) not null,           --操作说明
 OPERATOR nvarchar(20) not null,            --操作人
 OPER_TIME datetime not null,            --操作时间 
)

go

insert into BANK_ACCOUNTS (ACCOUNT_NUM, CUSTOMER_NAME, BALANCE) values ('20090101','张三',5000);
insert into BANK_ACCOUNTS (ACCOUNT_NUM, CUSTOMER_NAME, BALANCE) values ('20090102','李四',5000);
insert into BANK_ACCOUNTS (ACCOUNT_NUM, CUSTOMER_NAME, BALANCE) values ('20090103','王五',5000);
go

select * from bank_accounts;
go

--利用事务完成转帐过程
BEGIN TRANSACTION
update BANK_ACCOUNTS set BALANCE=BALANCE-5000 where ACCOUNT_NUM = '20090101';
if(@@ERROR <> 0)  --如果前面一条语句的执行过程出现了错误则回滚事务并结束批处理
begin
 ROLLBACK TRANSACTION
 return;
end
update BANK_ACCOUNTS set BALANCE=BALANCE+5000 where ACCOUNT_NUM = '20090103';
if(@@ERROR <> 0)
begin
 ROLLBACK TRANSACTION
 return;
end
insert into BANK_TRANS_LOGS(ACCOUNT_NUM,AMOUNT,DESCRIPTION,OPERATOR,OPER_TIME) values
 ('20090101',-5000,'转出','Tom',GetDate());
if(@@ERROR <> 0)
begin
 ROLLBACK TRANSACTION
 return;
end
insert into BANK_TRANS_LOGS(ACCOUNT_NUM,AMOUNT,DESCRIPTION,OPERATOR,OPER_TIME) values
 ('20090103',5000,'转入','Tom',GetDate());
if(@@ERROR <> 0)
begin
 ROLLBACK TRANSACTION
 return;
end
Commit TRANSACTION

go

--采用结构化错误处理流程处理事务回滚
declare @trans_amount float;
set @trans_amount = 2000;

SET XACT_ABORT ON; --设置当事务出错时中止事务执行

BEGIN TRY
 BEGIN TRANSACTION
 update BANK_ACCOUNTS set BALANCE=BALANCE-@trans_amount where ACCOUNT_NUM = '20090101';
 update BANK_ACCOUNTS set BALANCE=BALANCE+@trans_amount where ACCOUNT_NUM = '20090103';
 insert into BANK_TRANS_LOGS(ACCOUNT_NUM,AMOUNT,DESCRIPTION,OPERATOR,OPER_TIME) values
  ('20090101',-@trans_amount,'转出','Tom',GetDate());
 insert into BANK_TRANS_LOGS(ACCOUNT_NUM,AMOUNT,DESCRIPTION,OPERATOR,OPER_TIME) values
  ('20090103',@trans_amount,'转入','Tom',GetDate());
 Commit TRANSACTION
 print '转帐成功';
END TRY
BEGIN CATCH
 print '错误:' + convert(nvarchar,ERROR_NUMBER()) + ':' + ERROR_MESSAGE();
 if(XACT_STATE() = -1)
 begin
  ROLLBACK TRANSACTION
 end
END CATCH

go
select * from BANK_ACCOUNTS;
select * from BANK_TRANS_LOGS;
go

----游标高级选项演示

----只读、前向游标(FAST_FORWARD选项,速度最快,最节省资源的选项)
declare @acc_num nvarchar(20);
declare @cust_name nvarchar(20);
declare @balance float;

declare bankcur cursor FAST_FORWARD for select ACCOUNT_NUM, CUSTOMER_NAME, BALANCE from BANK_ACCOUNTS;
open bankcur;

fetch bankcur into @acc_num, @cust_name, @balance;

while(@@FETCH_STATUS = 0)
begin
 print '帐号:' + @acc_num + ' 姓名:' + @cust_name + ' 余额:' + convert(nvarchar,@balance);
 fetch bankcur into @acc_num, @cust_name, @balance;
end

close bankcur;
deallocate bankcur;
go

----利用游标更新数据(利用For update选项打开游标)

declare @acc_num nvarchar(20);
declare @cust_name nvarchar(20);
declare @balance float;

declare bankcur cursor for select ACCOUNT_NUM, CUSTOMER_NAME, BALANCE from BANK_ACCOUNTS for update;
open bankcur;

fetch bankcur into @acc_num, @cust_name, @balance;

while(@@FETCH_STATUS = 0)
begin
 if(@balance < 10000) --如果账户余额小于10000,则在账户上增加2000
 begin
  update bank_accounts set BALANCE=BALANCE+2000 where current of bankcur; --在游标当前指向的记录上更新
 end
 fetch bankcur into @acc_num, @cust_name, @balance;
end

close bankcur;
deallocate bankcur;

select * from bank_accounts;
go

----使用静态滚动游标(使用SCROLL和STATIC选项)
declare @acc_num nvarchar(20);
declare @cust_name nvarchar(20);
declare @balance float;

declare bankcur cursor SCROLL STATIC for select ACCOUNT_NUM, CUSTOMER_NAME, BALANCE from BANK_ACCOUNTS;
open bankcur;

----从前向后依次顺序取出数据
fetch bankcur into @acc_num, @cust_name, @balance;

while(@@FETCH_STATUS = 0)
begin
 print '帐号:' + @acc_num + ' 姓名:' + @cust_name + ' 余额:' + convert(nvarchar,@balance);
 fetch bankcur into @acc_num, @cust_name, @balance;
end

----绝对定位取出数据
fetch absolute 2 from bankcur into @acc_num, @cust_name, @balance; --(取第二条记录)
if(@@FETCH_STATUS = 0)
begin
 print '帐号:' + @acc_num + ' 姓名:' + @cust_name + ' 余额:' + convert(nvarchar,@balance);
end
else
begin
 print '记录不存在';
end
 
fetch absolute 4 from bankcur into @acc_num, @cust_name, @balance; --(取第四条记录)
if(@@FETCH_STATUS = 0)
begin
 print '帐号:' + @acc_num + ' 姓名:' + @cust_name + ' 余额:' + convert(nvarchar,@balance);
end
else
begin
 print '记录不存在';
end

----利用相对定位取出数据
fetch relative -2 from bankcur into @acc_num, @cust_name, @balance; --(取相对于当前位置的前面第二条记录)
if(@@FETCH_STATUS = 0)
begin
 print '帐号:' + @acc_num + ' 姓名:' + @cust_name + ' 余额:' + convert(nvarchar,@balance);
end
else
begin
 print '记录不存在';
end

fetch relative 1 from bankcur into @acc_num, @cust_name, @balance; --(取相对于当前位置的后面第一条记录)
if(@@FETCH_STATUS = 0)
begin
 print '帐号:' + @acc_num + ' 姓名:' + @cust_name + ' 余额:' + convert(nvarchar,@balance);
end
else
begin
 print '记录不存在';
end

----取前面一条记录
fetch prior from bankcur into @acc_num, @cust_name, @balance;
if(@@FETCH_STATUS = 0)
begin
 print '帐号:' + @acc_num + ' 姓名:' + @cust_name + ' 余额:' + convert(nvarchar,@balance);
end
else
begin
 print '记录不存在';
end

----取后面一条记录
fetch next from bankcur into @acc_num, @cust_name, @balance;
if(@@FETCH_STATUS = 0)
begin
 print '帐号:' + @acc_num + ' 姓名:' + @cust_name + ' 余额:' + convert(nvarchar,@balance);
end
else
begin
 print '记录不存在';
end

----取第一条记录
fetch first from bankcur into @acc_num, @cust_name, @balance;
if(@@FETCH_STATUS = 0)
begin
 print '帐号:' + @acc_num + ' 姓名:' + @cust_name + ' 余额:' + convert(nvarchar,@balance);
end
else
begin
 print '记录不存在';
end


----取最后一条记录
fetch last from bankcur into @acc_num, @cust_name, @balance;
if(@@FETCH_STATUS = 0)
begin
 print '帐号:' + @acc_num + ' 姓名:' + @cust_name + ' 余额:' + convert(nvarchar,@balance);
end
else
begin
 print '记录不存在';
end

close bankcur;
deallocate bankcur;
go

SET XACT_ABORT OFF
go

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值