项目名称:银行ATM存取款机系统设计与实现
一、创建数据库............................................................................................................. 3
1.1创建数据库....................................................................................................... 3
1.2创建各个数据表及相关的约束....................................................................... 3
1.3添加外键约束和生成数据库关系图............................................................... 6
二、创建触发器和插入测试数据................................................................................. 6
2.1创建级联触发器.............................................................................................. 6
2.2插入数据表的测试数据.................................................................................. 9
三、模拟常规业务....................................................................................................... 12
3.1修改客户密码................................................................................................. 12
3.2办理银行卡挂失............................................................................................ 12
3.3统计银行资金流通余额和盈利结算............................................................ 13
3.4查询本周开户信息........................................................................................ 14
3.5查询本月单次交易金额最高的卡号和总交易金额最高的卡号................ 14
3.6查询挂失客户................................................................................................ 15
3.7催款提醒业务................................................................................................ 15
四、创建、使用视图................................................................................................... 16
4.1输出银行客户记录视图VW_userInfo......................................................... 16
4.2输出银行卡记录视图VW_CardInfo............................................................. 16
4.3输出银行卡交易记录视图VW_TransInfo................................................... 17
4.4根据客户登录名查询该客户账户信息VW_OneUserInfo........................... 18
五、存储过程实现业务处理....................................................................................... 18
5.1完成存款或取款业务.................................................................................... 18
5.2产生随机卡号................................................................................................ 21
5.3完成开户业务................................................................................................ 22
5.4分页显示查询交易数据................................................................................ 24
5.5打印客户对账单............................................................................................ 25
5.6统计未发生交易的账户................................................................................ 27
5.7统计银行卡交易量和交易额........................................................................ 30
六、利用事务实现转账............................................................................................... 34
心得体会:................................................................................................................... 39
源代码:....................................................................................................................... 40
创建数据库
-- 创建数据库BankDB
-- 数据库文件和日志均保存在 D:\20160107SQL项目练习\银行ATM机器系统\
-- 文件大小为5MB增长15% 日志大小为3MB增长5MB
use master
if exists(select * from sysdatabases where name='BankDB')
drop database BankDB
go
create database BankDB
on
(
name='BankDB_Data',
filename='D:\20160107SQL\项目练习\银行ATM机器系统\BankDB01_Data.mdf',
size=5mb,
filegrowth=15%
)
log on
(
name='BankDB_Log',
filename='D:\20160107SQL\项目练习\银行ATM机器系统\BankDB01_Log.ldf',
size=3mb,
filegrowth=5mb
)
go
创建各个数据表及相关的约束
--创建银行业务类型表BankBusinessType
--判断银行业务类型表是否存在,若存在则删除
--创建银行业务类型表,包含银行业务类型编号BBTId主键 自动标识符,银行业务类型名称BBTName char(20) not null,银行业务描述BBTComment varchar(100)
use BankDB
if exists(select * from sysobjects where name='BankBusinessType')
drop table BankBusinessType
go
create table BankBusinessType
(
BBTId int identity(1,1) primary key,
BBTName char(20) not null,
BBTComment varchar(100)
)
go
--创建银行客户信息表BankCustomer
--判断银行卡客户是否存在,若存在则删除
--创建银行客户信息表,包含客户编号BCID 主键 自动标识符,客户姓名BCName char(20) not null,客户身份证BCICNo,客户联系电话BCTel、
客户居住地址BCAddr varchar(100)
--定义身份证号前位必须是数字,后位可以是数字或者X。
--定义联系方式,必须是固定电话号码或者手机号,固定电话号码前位必须是区号,手机号码前面第一位必须是1,第二位必须是[3,5,8,9]
if exists(select * from sysobjects where name='BankCustomer')
drop table BankCustomer
go
create table BankCustomer
(
--客户编号BCID 主键 自动标识符,
BCID int identity(1,1) primary key,
--客户姓名BCName char(20) not null,
BCName char(20) not null,
--客户身份证BCICNo,
BCICNo char(18) not null,
--客户联系电话BCTel
BCTel char(12) not null,
--客户居住地址BCAddr varchar(100)
BCAddr varchar(100)
)
go
--定义身份证号前位必须是数字,后位可以是数字或者X。
alter table BankCustomer add constraint CK_BCICNo check(BCICNo like
replicate('[0-9]',17)+replicate('[0-9xX]',1))
--定义联系方式,必须是固定电话号码或者手机号,固定电话号码前位必须是区号,
--手机号码前面第一位必须是1,第二位必须是[3,5,8,9]
alter table BankCustomer add constraint CK_BCTel check(BCTel like
'1'+replicate('[3589]',1)+replicate('[0-9]',9) or BCTel
like replicate('[0-9]',3)+'-'+replicate('[0-9]',8) or
BCTel like replicate('[0-9]',4)+'-'+replicate('[0-9]',7))
go
--建立银行卡信息 BankCard
--判断银行卡是否存在,若存在,则删除银行卡BankCard
-- 卡号 BCNo char(19) 主键 必须符合16位数字构成,前8位为1010 3576,后位是随机产生且唯一,每4位必须有一个空格
-- 密码 BCPwd char(6) not null ,开户默认为'888888'
-- 币种 BCCurrency char(5) not null, 默认为RMB类型
-- 存款类型 BCBBTId int not null
-- 开户日期 BCOpenDate datetime not null,默认当日
-- 开户金额 BCOpenAmount money not null ,不得小于1元
-- 是否挂失 BCRegLoss char(2),默认为否
-- 客户编号 BCBCId intnot null,
-- 当前余额 BCExistBalance money not null
if exists(select * from sysobjects where name='BankCard')
drop table BankCard
go
create table BankCard
(
-- 卡号 BCNo char(19) 主键
BCNo char(19) primary key,
-- 密码 BCPwd char(6) not null ,开户默认为'888888'
BCPwd char(6) not null default('888888'),
-- 币种 BCCurrency char(5) not null, 默认为RMB类型
BCCurrency char(5) not null default('RMB'),
-- 存款类型 BCBBTId int not null
BCBBTId int not null,
-- 开户日期 BCOpenDate datetime notnull,默认当日
BCOpenDate date not null default(convert(varchar(10),getdate(),120)),
-- 开户金额 BCOpenAmount money not null ,不得小于1元
BCOpenAmountmoney not null check(BCOpenAmount>=1),
-- 是否挂失 BCRegLoss char(2),默认为否
BCRegLoss char(2) default('否') check(BCRegLoss='是' or BCRegLoss='否'),
-- 客户编号 BCBCId int not null,
BCBCId int not null,
-- 当前余额 BCExistBalance moneynot null
BCExistBalancemoney not null
)
go
--卡号必须符合16位数字构成,前8位为1010 3576,
--后位是随机产生且唯一,每4位必须有一个空格
alter table BankCard add constraint CK_BCNo check(BCNo like'1010 3576 '+
replicate('[0-9]',4)+' '+replicate('[0-9]',4))
go
--创建交易信息表BankDealInfo
--判断交易信息BankDealInfo是否存在,若存在则删除
--交易编号BDNo 为自动增长列 主键
--卡号 BDBCNo char(19) not null
--交易日期 BDDealDate Datenot null 默认为当前日期
--交易金额 BDDealAcount money not null
--交易类型,有种存入和支取 BDDealType Char(10) not null
--交易备注 BDDealComment varchar(100)
if exists(select * from sysobjects where name='BankDealInfo')
drop table BankDealInfo
go
create table BankDealInfo
(
--交易编号BDNo 为自动增长列 主键
BDNo int identity(1,1) primary key,
--卡号 BDBCNo char(19) not null
BDBCNo char(19) not null,
--交易日期 BDDealDate Date notnull 默认为当前日期
BDDealDate Date not null default(convert(varchar(10),getdate(),120)),
--交易金额 BDDealAcount money notnull
BDDealAcountmoney not null,
--交易类型,有种存入和支取 BDDealTypeChar(10) not null
BDDealType Char(10) not null check(BDDealType like'存入'
or BDDealType like'支取'),
--交易备注 BDDealCommentvarchar(100)
BDDealCommentvarchar(100)
)
Go
添加外键约束和生成数据库关系图
--建立表之间的外键约束关系
alter table BankCard add constraint FK_BCBBTIdforeign key(BCBBTId)
references BankBusinessType(BBTId)
alter table BankCard add constraint FK_BCBCId foreign key(BCBCId)
references BankCustomer(BCID)
alter table BankDealInfo add constraint FK_BDBCNo foreign key(BDBCNo)
references BankCard(BCNo)
go
创建级联触发器
2.1.1创建Insert触发器
--在交易信息表中插入一个触发器tr_InsertdealInfo,修改银行卡的存款余额
--判断交易记录里是存入还是支取,及时更新银行卡表的存款余额
if exists(select * from sysobjects where name='tr_InsertdealInfo')
drop trigger tr_InsertdealInfo
go
create trigger tr_InsertdealInfo on BankDealInfo
for insert
as
declare @BDDealType Char(10),@BDDealAcount money,@BDBCNo char(19)
select @BDDealType=BDDealType,@BDDealAcount=BDDealAcount,@BDBCNo
=BDBCNo from inserted
if(@BDDealType='存入')
updateBankCard set BCExistBalance+=@BDDealAcount where BCNo=@BDBCNo
else
begin
if(convert(float,(select BCExistBalance from BankCard where
BCNo=@BDBCNo))<@BDDealAcount)
begin
raiserror('本卡的当前余额不足',18,100)
rollbacktran
end
else
updateBankCard set BCExistBalance-=@BDDealAcount where BCNo=@BDBCNo
end
go
2.1.2创建Delete触发器
--在交易信息表中插入一个触发器tr_DeldealInfo,当删除一个交易信息,修改银行卡的存款余额
if exists(select * from sysobjects where name='tr_DeldealInfo')
drop trigger tr_DeldealInfo
go
create trigger tr_DeldealInfo on BankDealInfo
instead of delete
as
declare @BDDealType Char(10),@BDDealAcount money,@BDBCNo char(19)
select @BDDealType=BDDealType,@BDDealAcount=BDDealAcount,@BDBCNo
=BDBCNo from deleted
if(@BDDealType='存入')
begin
if(convert(float,(select BCExistBalance from BankCard where
BCNo=@BDBCNo))<@BDDealAcount)
begin
raiserror('本卡的当前余额不足',18,100)
rollbacktran
end
else
updateBankCard set BCExistBalance-=@BDDealAcount where BCNo=@BDBCNo
end
else
updateBankCard set BCExistBalance+=@BDDealAcount where BCNo=@BDBCNo
go
2.1.3创建Update触发器
--在交易信息表中插入一个触发器,修改银行卡的存款余额
--判断交易记录里是存入还是支取,及时更新银行卡表的存款余额
if exists(select * from sysobjects where name='tr_updatedealInfo')
drop trigger tr_updatedealInfo
go
create trigger tr_updatedealInfo on BankDealInfo
for update
as
declare @oldDealType Char(10),@newDealType Char(10),@oldDealAcount
money,@newDealAcount money,@BDBCNo char(19)
select @BDBCNo=BDBCNo,@oldDealType=BDDealType,@oldDealAcount=
BDDealAcountfrom deleted
select @newDealType=BDDealType,@newDealAcount=BDDealAcount from inserted
if(@oldDealType=@newDealAcount)
begin
if(@oldDealType='存入')
updateBankCard set BCExistBalance+=@newDealAcount-@oldDealAcount
whereBCNo=@BDBCNo
else
begin
if(convert(float,(select BCExistBalance from BankCard where
BCNo=@BDBCNo))<@newDealAcount-@oldDealAcount)
begin
raiserror('本卡的当前余额不足',18,100)
rollbacktran
end
else
updateBankCard set BCExistBalance-=@newDealAcount-@oldDealAcount
whereBCNo=@BDBCNo
end
end
else
begin
if(@oldDealType='存入')
begin
if(convert(float,(select BCExistBalance from BankCard where
BCNo=@BDBCNo))<@newDealAcount+@oldDealAcount)
begin
raiserror('本卡的当前余额不足',18,100)
rollbacktran
end
else
updateBankCard set BCExistBalance-=@newDealAcount+@oldDealAcount
whereBCNo=@BDBCNo
end
else
begin
updateBankCard set BCExistBalance+=@newDealAcount-@oldDealAcount
whereBCNo=@BDBCNo
end
end
go
插入数据表的测试数据
--插入表的测试数据
insert into BankBusinessType
values('活期','无固定存储期,可随时存款,存款金额不限的一种比较灵活的存款'),
('定活俩便','事先不约定存期,一次性存入,一次性取出的存款'),
('通知','不约定存期,支取时需要提前通知银行,约定支取时间和金额方能支取的存款'),
('整存整取1年','整笔存入,到期提取本息'),('整存整取2年','整笔存入,到期提取本息'),
('整存整取3年','整笔存入,到期提取本息'),('零存整取1年',
'事先约定金额,逐月按约定金额存入,到期支付本息'),('零存整取2年',
'事先约定金额,逐月按约定金额存入,到期支付本息'),('零存整取3年',
'事先约定金额,逐月按约定金额存入,到期支付本息'),('自助转账',
'银行ATM存取款机上办理银行卡之间的相互转账')
select * from BankBusinessType
go
insert into BankCustomer values('张飞','150203197611154224','13088447030',
'包头市昆区宝钢五中'),('关羽','15020319761005123X','0472-2315490',
'包头昆区阿尔丁大街')
select * from BankCustomer
go
insert into BankCard values('1010 3576 1234 5678','197611',default,1,
'2018-05-28',1000,default,1,1000),('1010 3576 1234 5688','197711',
default,2,'2018-05-28',1500,default,2,1500)
select * from BankCard
go
insert into BankDealInfo values('1010 3576 1234 5678','2018-05-29',500,
'存入','单位1月工资')
insert into BankDealInfo values('1010 3576 1234 5678','2018-05-29',1500,'存入',
'单位2月工资')
insert into BankDealInfo values('1010 3576 1234 5678','2018-05-29',600,'支取',
'支付宝付款')
insert into BankDealInfo values('1010 3576 1234 5678','2018-05-29',700,'支取',
'刷卡消费')
insert into BankDealInfo values('1010 3576 1234 5688','2018-05-29',3000,'存入',
'单位1月工资')
insert into BankDealInfo values('1010 3576 1234 5688','2018-05-29',2800,'存入',
'单位2月工资')
insert into BankDealInfo values('1010 3576 1234 5688','2018-05-29',1600,'支取',
'支付宝付款')
insert into BankDealInfo values('1010 3576 1234 5688','2018-05-29',900,'支取',
'刷卡消费')
select * from BankDealInfo
select * from BankCard
go
修改客户密码
--修改客户密码
--根据卡号修改指定2个客户的银行密码,其中第一个客户1010 3576 1234 5678密码修改为123456,第二个客户1010 3576 1234 5688修改为123123.
update BankCardset BCPwd='123456' where BCNo='1010 3576 1234 5678'
update BankCardset BCPwd='123123' where BCNo='1010 3576 1234 5688'
go
-- 按照以下字段进行显示 '卡号', '密码', '货币类型', '存储类型','开户日期', '开户金额','是否挂失', '客户编号','存款金额'
select BCNo as 卡号,BCPwd as 密码,BCCurrency as 货币类型,BCBBTId as
存储类型,BCOpenDate as 开户日期,BCOpenAmount as 开户金额,BCRegLoss
as 是否挂失,BCBCId as 客户编号,BCExistBalance as 存款金额 from BankCard
go
办理银行卡挂失
--办理银行卡挂失
--卡号为1010 3576 1234 5678的银行卡丢失,申请挂失,要求使用innerjoin语句显示如下图运行结果:
update BankCardset BCRegLoss='是' where BCNo='1010 3576 1234 5688'
select BCNo as 卡号,BCPwd as 密码,BCCurrency as 货币类型,BBTName as
存储类型,BCOpenDate as 开户日期,BCOpenAmount as 开户金额,BCRegLoss
as 是否挂失,BCBCId as 客户编号,BCExistBalance as 存款金额 from BankCard
inner join BankBusinessType on BCBBTId=BBTId
go
统计银行资金流通余额和盈利结算
-- 使用存储过程 proc_BanlanceAndProfit,
-- 统计银行资金流通余额和盈利结算
-- 1.获取总存入金额和总支取金额
盈利余额=总存入金额*0.008-总支取金额*0.003
if exists(select * from sysobjects where name='proc_BanlanceAndProfit')
drop procedure proc_BanlanceAndProfit
go
create procedure proc_BanlanceAndProfit
as
declare @inMoney money=0,@outMoney money=0,@i int=1,@BDDealType Char(10),
@BDDealAcountmoney
while(@i<=convert(int,(select max(BDNo) from BankDealInfo)))
begin
select @BDDealType=BDDealType,@BDDealAcount=BDDealAcount from
BankDealInfowhere BDNo=@i
if(@BDDealType='存入')
set @inMoney+=@BDDealAcount
else if(@BDDealType='支取')
set @outMoney+=@BDDealAcount
set @i+=1
end
print '存入总金额:'+ltrim(str(@inMoney))+'RMB,支取总金额:'+
ltrim(str(@outMoney))+'RMB'
print '盈利余额为:'+ltrim(str(@inMoney*0.008-@outMoney*0.003))
go
exec proc_BanlanceAndProfit
go
查询本周开户信息
--查询本周开户信息
select BCNo as 卡号,BCPwd as 密码,BCCurrency as 货币类型,BBTName as
存储类型,BCOpenDate as 开户日期,BCOpenAmount as 开户金额,BCName as
客户姓名,BCExistBalance as 存款金额,BCRegLoss as 是否挂失,(case when
BCRegLoss='否' then '正常账户' else '挂失账户' end) as 账户状态 from
BankCard,BankCustomer,BankBusinessType where BCBBTId=BBTId and BCID=BCBCId
and datediff(ww,BCOpenDate,getdate())=0
go
查询本月单次交易金额最高的卡号和总交易金额最高的卡号
代码实现:
--查询
--1.本月单次交易金额最高的卡号
select top 1 BDBCNo as 卡号,BCOpenDate as 开户日期,BCOpenAmount as 开户金额
from BankCard,BankDealInfo,BankCustomer where BDBCNo=BCNo and BCID=BCBCId
and datediff(mm,BCOpenDate,getdate())=0 order by BDDealAcount desc
go
--2. 总交易金额最高的卡号
select top 1 BDBCNo as 卡号,BCOpenDate as 开户日期,BCOpenAmount as 开户金额
from BankCard,BankDealInfo,BankCustomer where BDBCNo=BCNo and BCID=BCBCId
group by BDBCNo,BCOpenDate,BCOpenAmount order by sum(BDDealAcount) desc
go
查询挂失客户
--查询挂失客户
--查询挂失账号的客户信息,分别利用子查询in的方式或者内部连接inner join,查询结果如下图所示:
select BCName as 客户姓名,BCTel as 客户电话 from BankCustomer where
BCID in(select BCBCId from BankCard where BCRegLoss='是')
go
催款提醒业务
--催款提醒业务
--根据某种业务(如代缴电话费、代缴手机费或房贷等)的需要,每个月末,查询出客户账户上余额少于2000元,由银行统一致电催款。
select BCName as 客户姓名,BCTel as 客户电话,BCExistBalance as 客户余额
from BankCustomer inner join BankCard on BCID=BCBCId where BCExistBalance<2000
go
输出银行客户记录视图VW_userInfo
为向客户提供友好的用户界面,使用T-SQL语句创建下面几个视图,并使用这些视图输出各表信息。
--输出银行客户记录视图VW_userInfo
--显示的列名全为中文,要求先判断该视图是否存在,若存在,则先删除。结果如下图所示:
if exists(select * from sysobjects where name='VW_userInfo')
drop view VW_userInfo
go
create view VW_userInfo
as
select BCID as 客户编号,BCName as 开户名,BCICNo as 身份证号,BCTel
as 电话号码,BCAddr as 居住地址 from BankCustomer
go
select * from VW_userInfo
go
输出银行卡记录视图VW_CardInfo
--(2)输出银行卡记录视图VW_CardInfo
if exists(select * from sysobjects where name='VW_CardInfo')
drop view VW_CardInfo
go
create view VW_CardInfo
as
select BCNo as 卡号,BCName as 开户名,BCCurrency as 货币类型,BBTName as
存储类型,BCOpenDate as 开户日期,BCExistBalance as 存款金额,BCPwd as 密码
,BCRegLoss as 是否挂失 from BankCard,BankBusinessType,BankCustomer
where BBTId=BCBBTId and BCID=BCBCId
go
select * from VW_CardInfo
go
输出银行卡交易记录视图VW_TransInfo
--输出银行卡交易记录视图VW_TransInfo
--查询该视图,结果如下图所示:
if exists(select * from sysobjects where name='VW_TransInfo')
drop view VW_TransInfo
go
create view VW_TransInfo
as
select BDDealDate as 交易日期,BDDealType as 交易类型,BDBCNo as 交易卡号,
BDDealAcountas 交易金额,BDDealComment as 备注 from BankDealInfo
go
select * from VW_TransInfo
go
根据客户登录名查询该客户账户信息VW_OneUserInfo
--根据客户登录名查询该客户账户信息VW_OneUserInfo
if exists(select * from sysobjects where name='VW_OneUserInfo')
drop view VW_OneUserInfo
go
create view VW_OneUserInfo
as
select BCID as 客户编号,BCName as 开户名,BCICNo as 身份证号,BCTel
as 电话号码,BCAddr as 居住地址 from BankCustomer where BCName=system_user
go
select * from VW_OneUserInfo
go
完成存款或取款业务
描述:
Ø 根据银行卡号和交易金额实现银行卡的存款和取款业务。
Ø 每一笔存款,取款业务都要计入银行交易账户,并同时更新客户的存款余额。
Ø 如果是取款业务,在记账之前,要完成下面两项数据的检查验证工作,如果检查不合格,那么中断取款业务,给出提示信息后退出。
² 检查客户输入的密码是否正确。
² 账户取款金额是否大于当前存款额加1。
要求:
Ø 取款或存款存储过程名为usp_takeMoney。
Ø 编写一个存储过程完成存款和取款业务,并调用存储过程取钱或者存钱进行测试,测试数据是张飞的卡号支取100元(密码123456),关羽的卡号存入2100元。
Ø
--创建存取款业务的存储过程proc_TakeMoney
--完成存款或取款业务
if exists(select * from sysobjects where name='proc_TakeMoney')
drop procedure proc_TakeMoney
go
create procedure proc_TakeMoney @bcno char(19),@saleMoney money,@pwd char(6)=null
as
declare @existBanlance money,@errorCount int =0
begin tran
select @existBanlance=BCExistBalance from BankCard where BCNo=@bcno
--不返回受影响的行数
set nocount on
print '交易前,卡号'+@bcno+',余额为:'+ltrim(str(@existBanlance))
print '交易正进行,请稍后...'
--如果输入参数@pwd为空,则为存款业务,否则为取款业务
if (@pwd is not null)
begin
--1. 办理取款业务
--判断指定卡号和密码是否存在,若存在,则可以取款,否则不能办理取款业务
--判断取款金额是否小于等于存款余额-1,若条件成立,则可以取款,否则不能取款
if exists(select * from BankCard where BCNo=@bcno and BCPwd=@pwd)
begin
if(convert(money,(select BCExistBalance from BankCard where
BCNo=@bcno and BCPwd=@pwd))-1<=@saleMoney)
raiserror('存款余额不足,不能办理取款业务!!',15,1)
else
begin
set@existBanlance-=@saleMoney
insertinto BankDealInfovalues(@bcno,default,@saleMoney,'支取','取款')
set@errorCount+=@@error
end
end
else
raiserror('不能办理取款业务!!',15,1)
end
else
begin
--2. 办理存款业务
--判断事务处理里是否有异常,若没有异常,则提交,若有异常,则回滚
--判断该交易为何种类型业务,若是存款,则现有余额等于原有余额加上存款金额
set @existBanlance+=@saleMoney
insert into BankDealInfo values(@bcno,default,@saleMoney,'存入','存款')
set @errorCount+=@@error
end
if @errorCount<>0
begin
rollback tran
raiserror('支取失败!!',18,2)
end
else
commit tran
print '交易成功,交易金额为:'+ltrim(str(@saleMoney))
print '卡号'+@bcno+',余额为:'+ltrim(str(@existBanlance))
go
--执行存款存储过程
exec proc_TakeMoney'1010 3576 1234 5678',2100
--执行取款存储过程
exec proc_TakeMoney'1010 3576 1234 5678',100,'123456'
select * from BankCard
select * from BankDealInfo
go
产生随机卡号
--使用存储过程 Proc_randCardID 产生随机卡号
--随机生成后8位卡号 [rand() 随机数 ]
-- 再把前面的8位补上 '1010 3576'
-- 最后判断卡号是否存在,如果存在则重新生成卡号的过程
if exists(select * from sysobjects where name='proc_randCardId')
drop procedure proc_randCardId
go
create procedure proc_randCardId @myCardId1varchar(19) output
as
while(1=1)
begin
declare @num1 char(4),@num2 char(4)
set @num1=convert(int,rand()*10000)
set @num2=convert(int,rand()*10000)
set @num1=replicate(0,4-len(@num1))+@num1
set @num2=replicate(0,4-len(@num2))+@num2
set @myCardId1='1010 3576 '+@num1+' '+@num2
if(@myCardId1 not in(select BCNo from BankCard))
break
end
go
declare @myCardId1 varchar(19)
exec proc_randCardId@myCardId1 output
print '产生随机卡号为:'+@myCardId1
go
完成开户业务
描述:
Ø 利用存储过程为客户开设2个银行卡账户,开户时需要提供客户的信息有:开户名、身份证号、电话号码、开户金额、存款类型和地址。客户的信息见表所示:
Ø 为成功开户的客户提供银行卡,且银行卡号唯一。
要求:
Ø 开户的存储过程名为usp_openAccount。
Ø 使用下面的数据执行该存储过程,进行测试:调用此存储过程开户。
--完成开户业务
--创建开户存储过程usp_openAccount,输入参数分别是开户名、身份证号、
--电话号码、开户金额、存款类型和地址
if exists(select * from sysobjects where name='usp_openAccount')
drop procedure usp_openAccount
go
create procedure usp_openAccount @BCNamechar(20),@BCICNo char(18),
@BCTel char(12),@BCOpenAmount money,@BBTName char(20),@BCAddr varchar(100)
as
--先判断存款类型是否正确
if exists(select BBTName from BankBusinessType whereBBTName=@BBTName)
begin
declare @errorCount int =0
begin tran
--插入一条客户信息记录
insert into BankCustomer values(@BCName,@BCICNo,@BCTel,@BCAddr)
set @errorCount+=@@error
--得到刚插入的客户信息的编号
declare @BCID int,@BCNo char(19)
select @BCID=max(BCID) from BankCustomer
--插入一条新开银行卡记录
exec proc_randCardId@BCNo output
insert into BankCard values(@BCNo,default,default,(select BBTId from
BankBusinessTypewhere BBTName=@BBTName),default,@BCOpenAmount,default,
@BCID,@BCOpenAmount)
set @errorCount+=@@error
--判断上述事务操作是否有异常
--1.如果错误 '尊敬的客户,开户不成功,所有操作均撤销'
if @errorCount<>0
begin
rollbacktran
raiserror('尊敬的客户,开户不成功,所有操作均撤销!!',18,2)
end
-- 2. 如果成功 '尊敬的客户,开户成功,系统为你产生的
--随机卡号是'+@BCNo
else
begin
print'尊敬的客户,开户成功,系统为你产生的'
print'随机卡号是'+@BCNo
committran
end
end
else
--错误显示 '尊敬的客户,未能成功开户,存款类型不正确,请重新输入'
raiserror('尊敬的客户,未能成功开户,存款类型不正确,请重新输入',15,1)
go
--执行开户过程
exec dbo.usp_openAccount'周公旦','150203197510074339','0472-2457890','1200.00',
'定活俩便','内蒙古包头'
exec dbo.usp_openAccount'姬昌','150203197610174339','0472-2457890','1300.00',
'活期','内蒙古包头'
exec dbo.usp_openAccount'白天磊','150207199301252316','18347261609','10000000',
'通知','内蒙古包头'
exec dbo.usp_openAccount'白天帅','150203197510074339','15102274286','1200.00',
'定活俩便','天津'
go
--显示开户的客户信息和银行卡信息
--'客户编号', '开户名', '身份证号', '电话号码', '居住地址',
--'卡号', '客户', '货币种类', '存款类型', '余额', '密码', '是否挂失'
select BCID as 客户编号,BCName as 开户名,BCICNo as 身份证号,BCTel
as 电话号码,BCAddr as 居住地址 from BankCustomer
go
select BCNo as 卡号,BCName as 客户,BCCurrency as 货币类型,BBTName as
存款类型,BCExistBalance as 余额,BCPwd as 密码,BCRegLoss as 是否挂失
from BankCard,BankBusinessType,BankCustomer where BBTId=BCBBTId
and BCID=BCBCId
go
分页显示查询交易数据
--分页显示查询交易数据
--根据指定的页数和每页的记录数分页显示交易数据。要求:
-- 显示第2页 的5条信息
if exists(select * from sysobjects where name='usp_PagingDisplay')
drop procedure usp_PagingDisplay
go
create procedure usp_PagingDisplay @pageint,@info int
as
select top(@page*@info) * from BankDealInfo where BDNo not in(select
top((@page-1)*@info) BDNo from BankDealInfo)
go
exec usp_PagingDisplay2,5
go
打印客户对账单
为某个特定的银行卡号打印指定时间内发生交易的对账单。要求如下:
Ø 存储过程名称是usp_CheckSheet。
Ø 分别采用以下两种方式执行存储过程,结果如下图所示。
² 如果不指定交易时间段,那么打印指定卡号的所有交易记录,如测试命令:exec usp_CheckSheet '1010 3576 1234 5688'
² 如果指定交易时间段,那么打印指定卡号在指定时间内发生的所有交易记录,如测试命令:
--(5)打印客户对账单
--创建客户对账单的存储过程usp_CheckSheet
--判断客户对账单存储过程是否存在,若是存在,则删除
if exists(select * from sysobjects where name='usp_CheckSheet')
drop procedure usp_CheckSheet
go
create procedure usp_CheckSheet @BCNo char(19),@startTime date=null,
@endTime date=null
as
declare @BCName char(20),@BCCurrency char(5),@BBTName char(20),
@BCOpenDate date,@i int=0
select @BCName=BCName,@BCCurrency=BCCurrency,@BBTName=BBTName,
@BCOpenDate=BCOpenDate from BankCustomer,BankBusinessType,BankCard
where BCID=BCBCId and BBTId=BCBBTId and BCNo=@BCNo
print '卡号:'+@BCNo
print '姓名:'+@BCName
print '货币:'+@BCCurrency
print '存款类型:'+@BBTName
print '开户日期:'+convert(char,@BCOpenDate)
print '交易日 '+'类型 '+'交易金额 '+'备注'
--打印客户对账单
while(@i<=convert(int,(select max(BDNo) from BankDealInfo)))
begin
declare @BDDealDate date,@BDDealType char(10),@BDDealAcount money,
@BDDealCommentvarchar(100)
if(@startTime is null)
set @startTime=dateadd(dd,-convert(int,datename(dd,getdate()))+1,
getdate())
if(@endTime is null)
set @endTime=getdate()
select @BDDealDate=BDDealDate,@BDDealType=BDDealType,@BDDealAcount
=BDDealAcount,@BDDealComment=BDDealComment from BankDealInfo where
BDBCNo=@BCNo and datediff(dd,@startTime,BDDealDate)>=0 and datediff
(dd,@endTime,BDDealDate)<=0 and BDNo=@i
if(@BDDealDate is not null and @BDDealType is not null and @BDDealAcount
is not null and @BDDealComment is not null)
printrtrim(convert(char,@BDDealDate))+' '+rtrim(ltrim(@BDDealType))
+' '+ltrim(convert(char,@BDDealAcount))+' '+@BDDealComment
set @BDDealDate=null
set @BDDealType=null
set @BDDealAcount=null
set @BDDealComment=null
set @i+=1
end
go
--执行打印客户对账单
exec usp_CheckSheet'1010 3576 1234 5688','2018-05-15','2018-06-15'
exec usp_CheckSheet'1010 3576 1234 5678'
go
统计未发生交易的账户
查询统计指定时间段内没有发生交易的账户信息。
要求:
存储过程名称是usp_getWithoutTrade。
指定时间段
如果没有指定起始日期,那么自本月1日开始进行统计,如果没有指定终止日期,那么截止到当日为止。
要求采用游标技术打印未发生交易的客户信息,参考客户对账单的代码。
该存储过程的执行结果如下图所示
--统计未发生交易的账户
if exists(select * from sysobjects where name='usp_getWithoutTrade')
drop procedure usp_getWithoutTrade
go
create procedure usp_getWithoutTrade @startTimedate=null,@endTime date=null
as
begin
if(@startTime is null)
set @startTime=dateadd(dd,-convert(int,datename(dd,getdate()))+1,
getdate())
if(@endTime is null)
set @endTime=getdate()
declare cur_BankCustomer cursorforward_only forselect distinct
BCID,BCName,BCICNo,BCTel,BCAddr from BankCustomer inner join
BankCard on BCID=BCBCId where BCNo not in(select BDBCNo
from BankDealInfo where datediff(dd,@endTime,BDDealDate)<=0
and datediff(dd,@startTime,BDDealDate)>=0)
open cur_BankCustomer
declare @i int=0,@BCExistBalance money,@sumMoney money=0
print '客户编号 '+'客户姓名 '+'身份证号 '+' 电话号码 '+' 地址'
while(1=1)
begin
declare @BCID int,@BCName char(20),@BCICNo char(18),@BCTel char(12),
@BCAddr varchar(20)
fetch next from cur_BankCustomer into@BCID,@BCName,@BCICNo,@BCTel,@BCAddr
if @@fetch_status<>0
break
print convert(char(11),@BCID)+rtrim(@BCName)+' '+@BCICNo+' '+@BCTel+
' '+@BCAddr
set @i+=1
select @BCExistBalance=BCExistBalance from BankCard where BCBCId=@BCID
set @sumMoney+=@BCExistBalance
end
close cur_BankCustomer
deallocate cur_BankCustomer
print '统计为发生交易的人数:'+ltrim(str(@i))+'人,客户总余额为:'+
ltrim(str(@sumMoney))+'元'
end
go
exec usp_getWithoutTrade'2018-05-28','2018-05-28'
go
统计银行卡交易量和交易额
统计指定时间段内某地区客户在银行卡交易量和交易额,如果不指定地区,则查询所有客户的交易量和交易额。
要求:
Ø 存储过程名称是usp_getTradeInfo。
Ø 指定时间段和客户所在区域
如果没有指定起始日期,那么自当年1月1日开始统计,如果没有指定终止日期,那么以当日作为截止日。
如果没有指定地点(根据客户所在地址查询),如北京,那么统计全部客户的交易量和交易额。
--(7)统计银行卡交易量和交易额
--统计指定时间段内某地区客户在银行卡交易量和交易额,如果不指定地区,则查询所有客户的交易量和交易额。
if exists(select * from sysobjects where name='usp_getTradeInfo')
drop procedure usp_getTradeInfo
go
create procedure usp_getTradeInfo @startTimedate=null,@endTime date=null,
@addr varchar(100)=null
as
declare @inCount int=0,@outCount int=0,@inMoney money=0,@outMoney money=0,
@sumInMoney money=0,@sumOutMoney money=0,@i int=1
while(@i<=convert(int,(select max(BDNo) from BankDealInfo)))
begin
if(@startTime is null)
set @startTime=dateadd(mm,-convert(int,datename(mm,getdate()))
+1,dateadd(dd,-convert(int,datename(dd,getdate()))+1,getdate()))
if(@endTime is null)
set @endTime=getdate()
if(@addr is null)
begin
select@inCount=count(*) from BankDealInfo where BDDealType='存入'
and datediff(dd,@startTime,BDDealDate)>=0 and datediff(dd,@endTime,
BDDealDate)<=0
select@inMoney=BDDealAcount from BankDealInfo where BDDealType
='存入' and BDNo=@i and datediff(dd,@startTime,BDDealDate)>=0
and datediff(dd,@endTime,BDDealDate)<=0
set @sumInMoney+=@inMoney
select@outCount=count(*) from BankDealInfo where BDDealType='支取'
and datediff(dd,@startTime,BDDealDate)>=0 and datediff(dd,@endTime,
BDDealDate)<=0
select@outMoney=BDDealAcount from BankDealInfo where BDDealType
='支取' and BDNo=@i and datediff(dd,@startTime,BDDealDate)>=0
and datediff(dd,@endTime,BDDealDate)<=0
set @sumOutMoney+=@outMoney
end
else
begin
select@inCount=count(*) from BankDealInfo where BDDealType='存入'
and datediff(dd,@startTime,BDDealDate)>=0 and datediff(dd,@endTime,
BDDealDate)<=0 and BDBCNo in(select BCNo from BankCard where
BCBCIdin(select BCID from BankCustomer where BCAddr=@addr))
select@inMoney=BDDealAcount from BankDealInfo where BDDealType
='存入' and BDNo=@i and datediff(dd,@startTime,BDDealDate)>=0
and datediff(dd,@endTime,BDDealDate)<=0 and BDBCNo in(select BCNo
from BankCard where BCBCId in(select BCID from BankCustomer
whereBCAddr=@addr))
set @sumInMoney+=@inMoney
select@outCount=count(*) from BankDealInfo where BDDealType='支取'
and datediff(dd,@startTime,BDDealDate)>=0 and datediff(dd,@endTime,
BDDealDate)<=0 and BDBCNo in(select BCNo from BankCard where
BCBCIdin(select BCID from BankCustomer where BCAddr=@addr))
select@outMoney=BDDealAcount from BankDealInfo where BDDealType
='支取' and BDNo=@i and datediff(dd,@startTime,BDDealDate)>=0
and datediff(dd,@endTime,BDDealDate)<=0 and BDBCNo in(select BCNo
from BankCard where BCBCId in(select BCID from BankCustomer
whereBCAddr=@addr))
set @sumOutMoney+=@outMoney
end
set @i+=1
end
print '---------------------------------------------------------------'
print '---------------------------------------------------------------'
print '统计银行卡交易量和交易额'
print '起始日期:'+convert(char(21),@startTime)+'截止日期:'+convert(char,@endTime)
print '存入笔数:'+ltrim(str(@inCount))+' 存入金额:'
+ltrim(str(@sumInMoney))
print '支出笔数:'+ltrim(str(@outCount))+' 支出金额:'
+ltrim(str(@sumOutMoney))
print '交易总笔数:'+ltrim(str(@inCount+@outCount))
print '结余金额:'+ltrim(str(@sumInMoney-@sumOutMoney))
print '---------------------------------------------------------------'
print '---------------------------------------------------------------'
go
exec usp_getTradeInfo
exec usp_getTradeInfo@addr='包头市昆区宝钢五中'
exec usp_getTradeInfo'2018-05-1','2018-05-28'
exec usp_getTradeInfo'2018-05-1','2018-12-30','包头市昆区宝钢五中'
exec usp_getTradeInfo@addr='内蒙古包头'
go
利用事务实现转账
使用存储过程和事务实现转账业务,操作步骤如下所示:
(1) 从某一个账户支取一定金额的存款。
(2) 将支取金额存入到另一个指定的账户中。
(3) 分别打印此笔业务的转出账单和转入账单。
要求:
(1) 存储过程名称是usp_transfer。
(2) 要求使用事务机制实现转账业务。
if exists(select * from sysobjects where name='usp_transfer')
drop procedure usp_transfer
go
create procedure usp_transfer @outBCNochar(19),@inBCNo char(19),@saleMoney money
as
declare @errorCount int =0,@outBCExistBalance money,@inBCExistBalance money
begin tran
--不返回受影响的行数
set nocount on
insert into BankDealInfo values(@outBCNo,default,@saleMoney,'支取','通过存储')
set @errorCount+=@@error
insert into BankDealInfo values(@inBCNo,default,@saleMoney,'存入','通过存储')
set @errorCount+=@@error
if @errorCount<>0
begin
rollback tran
raiserror('转账失败!!',18,2)
end
else
begin
commit tran
print '开始转账,请稍后...'
print '交易正进行,请稍后...'
print '交易成功,交易金额:'+ltrim(str(@saleMoney))
select @outBCExistBalance=BCExistBalance from BankCard where
BCNo=@outBCNo
print '卡号:'+@outBCNo+' 余额:'+ltrim(str(@outBCExistBalance))
select @inBCExistBalance=BCExistBalance from BankCard where
BCNo=@inBCNo
print '卡号:'+@inBCNo+' 余额:'+ltrim(str(@inBCExistBalance))
declare @outBCName char(20),@outBCCurrency char(5),@outBBTName
char(20),@outBCOpenDate date
select @outBCName=BCName from BankCustomer where BCID=(select BCBCId from
BankCard where BCNo=@outBCNo)
select @outBCCurrency=BCCurrency,@outBCOpenDate=BCOpenDate from
BankCard where BCNo=@outBCNo
select @outBBTName=BBTName from BankBusinessType whereBBTId=(select
BCBBTId from BankCard where BCNo=@outBCNo)
print '打印出转出对账单'
print '---------------------------------------------------------------'
print '卡号:'+@outBCNo
print '货币类型:'+@outBCCurrency
print '存款类型:'+@outBBTName
print '开户日期:'+convert(char,@outBCOpenDate)
print '交易日 '+' 类型 '+'交易金额 '+'备注'
print convert(char(10),getdate(),120)+' 支取 '+ltrim(str(@saleMoney))+
' 通过存储'
declare @inBCName char(20),@inBCCurrency char(5),@inBBTName
char(20),@inBCOpenDate date
select @inBCName=BCName from BankCustomer where BCID=(select BCBCId from
BankCard where BCNo=@inBCNo)
select @inBCCurrency=BCCurrency,@inBCOpenDate=BCOpenDate from
BankCard where BCNo=@inBCNo
select @inBBTName=BBTName from BankBusinessType whereBBTId=(select
BCBBTId from BankCard where BCNo=@inBCNo)
print '打印出转入对账单'
print '---------------------------------------------------------------'
print '卡号:'+@inBCNo
print '货币类型:'+@inBCCurrency
print '存款类型:'+@inBBTName
print '开户日期:'+convert(char,@inBCOpenDate)
print '交易日 '+' 类型 '+'交易金额 '+'备注'
print convert(char(10),getdate(),120)+' 存入 '+ltrim(str(@saleMoney))+
' 通过存储'
print '---------------------------------------------------------------'
end
go
exec usp_transfer'1010 3576 1234 5678','1010 3576 1234 5688',100
go