--=========================第一阶段====================================================================
/*$$$$$$$$$$$$$ 创建文件夹 $$$$$$$$$$$$$$$$$$*/
use master
go
exec xp_cmdshell 'mkdir c:\bank', no_output--扩展存储过程.
--==========================================
declare @result int
exec @result = xp_cmdshell 'dir c:\bank\*.exe'
if (@result = 0)
print 'success'
else
print 'failure'
--=========================================
/*$$$$$$$$$$$$$建库$$$$$$$$$$$$$$$$$$$$$$$$*/
--检验数据库是否存在,如果为真,删除此数据库--
if exists(select * from sysdatabases where name = 'bankdb')
drop database bankdb
go
--创建建库bankdb
create database bankdb
on
(
name='bankdb_data',
filename='c:\bank\bankdb_data.mdf',
size=3mb,
filegrowth=15%
)
log on
(
name= 'bankdb_log',
filename='c:\bank\bankdb_log.ldf',
size=3mb,
filegrowth=15%
)
go
/*$$$$$$$$$$$$$建表$$$$$$$$$$$$$$$$$$$$$$$$*/
use bankdb
go
create table userinfo --用户信息表
(
customerid int identity(1,1),--顾客编号
customername char(8) not null,--顾客姓名
pid char(18) not null,--身份证号
telephone char(13) not null,--电话号码
address varchar(50) --地址
)
go
create table cardinfo --银行卡信息表
(
cardid char(19) not null,--卡号
curtype char(5) not null,--货币类型
savingtype char(8) not null,--存款类型
opendate datetime not null,--开户日期
openmoney money not null,--开户金额
balance money not null,--余额
pass char(6) not null,--密码
isreportloss bit not null,--是否挂失
customerid int not null--顾客卡号
)
go
create table transinfo --交易信息表
(
id int identity(1,1)Constraint PK_Transinfo_Id Primary Key,--ID主键
transdate datetime not null,--交易日期
transtype char(4) not null,--交易类型
cardid char(19) not null,--卡号
transmoney money not null,--交易金额
remark text --备注
)
go
/*$$$$$$$$$$$$$加约束$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
/* userinfo 表的约束
customerid 顾客编号 自动编号(标识列),从1开始,主键
customername 开户名 必填
pid 身份证号 必填,只能是18位或15位,身份证号唯一约束
telephone 联系电话 必填,格式为xxxx-xxxxxxxx或手机号13位
address 居住地址 可选输入
*/
alter table userinfo
add constraint pk_customerid primary key(customerid),
constraint ck_pid check( len(pid)=18 or len(pid)=15 ),
constraint uq_pid unique(pid),
constraint ck_telephone check( telephone like '[0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]' or telephone like '[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]' or len(telephone)=13 )
go
/*cardinfo表的约束
cardid 卡号 必填,主健 , 银行的卡号规则和电话号码一样,一般前8位代表特殊含义,
如某总行某支行等。假定该行要求其营业厅的卡号格式为:1010 3576 xxxx xxx开始
curtype 货币 必填,默认为rmb
savingtype 存款种类 活期/定活两便/定期
opendate 开户日期 必填,默认为系统当前日期
openmoney 开户金额 必填,不低于1元
balance 余额 必填,不低于1元,否则将销户
pass 密码 必填,6位数字,默认为6个8
isreportloss 是否挂失 必填,是/否值,默认为”否”
customerid 顾客编号 必填,表示该卡对应的顾客编号,一位顾客可以办理多张卡
*/
alter table cardinfo
add constraint pk_cardid primary key(cardid),
constraint ck_cardid check(cardid like '1010 3576 [0-9][0-9][0-9][0-9] [0-9][0-9][0-9][0-9]'),
constraint df_curtype default('rmb') for curtype,
constraint ck_savingtype check(savingtype in ('活期','定活两便','定期')),
constraint df_opendate default(getdate()) for opendate,
constraint ck_openmoney check(openmoney>=1),
constraint ck_balance check(balance>=1),
constraint ck_pass check(pass like '[0-9][0-9][0-9][0-9][0-9][0-9]'),
constraint df_pass default('888888') for pass,
constraint df_isreportloss default(0) for isreportloss,
constraint fk_customerid foreign key(customerid) references userinfo(customerid)
go
/* transinfo表的约束
transtype 必填,只能是存入/支取
cardid 卡号 必填,外健,可重复索引
transmoney 交易金额 必填,大于0
transdate 交易日期 必填,默认为系统当前日期
remark 备注 可选输入,其他说明
*/
alter table transinfo
add constraint ck_transtype check(transtype in ('存入','支取')),
constraint fk_cardid foreign key(cardid) references cardinfo(cardid),
constraint ck_transmoney check(transmoney>0),
constraint df_transdate default(getdate()) for transdate
go
--=========================第二阶段====================================================================
/*$$$$$$$$$$$$$插入测试数据$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
/*
张三开户,身份证:123456789012345,电话:010-67898978,地址:北京海淀
开户金额:1000 活期 卡号:1010 3576 1234 5678
李四开户,身份证:321245678912345678,电话:0478-44443333,
开户金额: 1 定期 卡号:1010 3576 1212 1134
*/
set nocount on --不显示受影响的条数信息
insert into userinfo(customername,pid,telephone,address)
values('张三','123456789012345','010-67898978','北京海淀')
insert into cardinfo(cardid,savingtype,openmoney,balance,customerid)
values('1010 3576 1234 5678','活期',1000,1000,1)
insert into userinfo(customername,pid,telephone)
values('李四','321245678912345678','0478-44443333')
insert into cardinfo(cardid,savingtype,openmoney,balance,customerid)
values('1010 3576 1212 1134','定期',1,1,2)
select * from userinfo
select * from cardinfo
go
/*
张三的卡号(1010 3576 1234 5678)取款900元,
李四的卡号(1010 3576 1212 1134)存款5000元,
要求保存交易记录,以便客户查询和银行业务统计。
说明:
当存钱或取钱(如300元)时候,
会往交易信息表(transinfo)中添加一条交易记录,
同时应更新银行卡信息表(cardinfo)中的现有余额(如增加或减少500元)
*/
/*--------------交易信息表插入交易记录--------------------------*/
insert into transinfo(transtype,cardid,transmoney)
values('支取','1010 3576 1234 5678',900)
/*-------------更新银行卡信息表中的现有余额-------------------*/
update cardinfo
set balance=balance-900
where cardid='1010 3576 1234 5678'
/*--------------交易信息表插入交易记录--------------------------*/
insert into transinfo(transtype,cardid,transmoney)
values('存入','1010 3576 1212 1134',5000)
/*-------------更新银行卡信息表中的现有余额-------------------*/
update cardinfo
set balance=balance+5000
where cardid='1010 3576 1212 1134'
go
/*--------检查测试数据是否正确---------*/
select * from cardinfo
select * from transinfo
/*$$$$$$$$$$$$$常规业务操作$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
/*---------修改密码-----*/
--1.张三(卡号为1010 3576 1234 5678)修改银行卡密码为123456
--2.李四(卡号为1010 3576 1212 1134)修改银行卡密码为123123
update cardinfo
set pass='123456'
where cardid='1010 3576 1234 5678'
update cardinfo
set pass='123123'
where cardid='1010 3576 1212 1134'
select * from cardinfo
/*---------挂失帐号---------*/
--李四(卡号为1010 3576 1212 1134)因银行卡丢失,申请挂失
update cardinfo
set isreportloss=1
where cardid='1010 3576 1212 1134'
select * from cardinfo
go
/*--------查询余额3000~6000之间的定期卡号,
显示该卡相关信息-----------------*/
select *
from cardinfo
where ((balance between 3000 and 6000) and (savingtype='定期'))
/*--------统计银行的 资金流通余额 和 盈利 结算------------------------------*/
-- 统计说明: 存款代表资金流入 , 取款代表资金流出.
-- 假定存款利率为千分之3 , 贷款利率为千分之 8
declare @inmoney money
declare @outmoney money
declare @profit money
select * from transinfo
select @inmoney = sum(transmoney) from transinfo where (transtype = '存入')
select @outmoney = sum(transmoney) from transinfo where (transtype = '支取')
print '银行流通余额总为:' + convert(varchar(20),@inmoney - @outmoney) + 'rmb'
set @profit = @outmoney*0.008 - @inmoney*0.003
print '盈利结算为:'+ convert(varchar(20),@profit) + 'rmb'
go
select * from transinfo
/*-------- 查询 本周开户的卡号,显示该卡相关信息 -----------------*/
select *
from cardinfo
where (datediff(day,getdate(),opendate) < datepart(weekday,opendate))
--select datepart(weekday,'2007-01-10')
/*---------查询本月交易金额最高的 卡号----------------------*/
select * from transinfo
select distinct cardid from transinfo
where transmoney = (
select max(transmoney) from transinfo
)
/*---------查询挂失帐号的 客户信息---------------------*/
select * from userinfo --客户信息表
select * from cardinfo --卡号信息表
select customername as 客户姓名,telephone as 联系电话
from userinfo
where customerid in (
select customerid from cardinfo where isreportloss = 1
)
/*------催款提醒:
例如 某种业务的需要,每个月末,
如果发现用户帐上余额少于200元,将致电催款。---*/
select customername as 客户姓名,telephone as 联系电话,balance as 帐上余额
from userinfo inner join cardinfo
on userinfo.customerid = cardinfo.customerid
where balance < 200
--=========================第三阶段====================================================================
/*$$$$$$$$$$$$$索引和视图$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
--1.创建索引:给交易表的卡号 cardid 字段创建 重复 索引
create nonclustered index index_cardid
on transinfo(cardid)
with fillfactor = 70
go
--2.按指定 索引查询 张三(卡号为1010 3576 1212 1134)的交易记录
select * from transinfo (index = index_cardid)
where cardid='1010 3576 1234 5678'
go
--3.创建视图:为了向客户显示信息友好,查询各表要求字段全为中文字段名。
create view view_userinfo --银行卡信息表视图
as
select customerid as 客户编号,customername as 开户名, pid as 身份证号,telephone as 电话号码,address as 居住地址
from userinfo
go
select * from view_userinfo
----------
create view view_cardinfo --银行卡信息表视图
as
select cardid as 卡号,curtype as 货币种类, savingtype as 存款类型,opendate as 开户日期,
balance as 余额,pass 密码,isreportloss as 是否挂失,customerid as 客户编号 from cardinfo
go
select * from view_cardinfo
----------
create view view_transinfo --交易信息表视图
as
select transdate as 交易日期,transtype as 交易类型, cardid as 卡号,transmoney as 交易金额,
remark as 备注 from transinfo
go
select * from view_transinfo
----------
/*$$$$$$$$$$$$$触发器$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
--改进上述的存款或取款语句,当存钱或取钱(如500元)时候,会往交易信息表 transinfo 中添加一条交易记录,
--同时会自动更新用户信息表:userinfo 中的现有金额的变化(如增加/减少500元)
--drop trigger trig_trans
create trigger trig_trans on transinfo for insert
as
declare @mytranstype char(4),@outmoney money,@mycardid char(19)
select @mytranstype = transtype,@outmoney = transmoney ,@mycardid = cardid from inserted
declare @mybalance money
select @mybalance = balance from cardinfo where cardid = @mycardid
if (@mytranstype='支取')
if (@mybalance >= @outmoney+1)
update cardinfo set balance = balance - @outmoney where cardid = @mycardid
else
begin
raiserror ('交易失败!余额不足!',16,1)
rollback tran
print '卡号' + @mycardid + ' 余额:' + convert(varchar(20),@mybalance)
return
end
else
update cardinfo set balance=balance+@outmoney where cardid=@mycardid
print '交易成功!交易金额:'+convert(varchar(20),@outmoney)
select @mybalance=balance from cardinfo where cardid=@mycardid
print '卡号' + @mycardid + ' 余额:' + convert(varchar(20),@mybalance)
go
--测试触发器:张三的卡号支取1000,李四的卡号存入200
--现实中的取款机依靠读卡器读出张三的卡号,这里根据张三的名字查出考号来模拟
--select * from cardinfo
declare @card char(19)
select @card = cardid
from cardinfo inner join userinfo
on cardinfo.customerid = userinfo.customerid
where customername = '张三'
insert into transinfo(transtype,cardid,transmoney) values('支取',@card,1000)
go
--======================
declare @card char(19)
select @card = cardid
from cardinfo inner join userinfo
on cardinfo.customerid = userinfo.customerid
where customername='李四'
insert into transinfo(transtype,cardid,transmoney) values('存入',@card,200)
go
--=========================第四阶段====================================================================
/*$$$$$$$$$$$$$$$$$$$$$$存储过程$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
--1.取钱或存钱的存储过程
--drop proc proc_takemoney
create procedure proc_takemoney
@card char(19),@m money,@type char(4),@inputpass char(6)=''
as
print '交易正进行,请稍后......'
if (@type='支取')
if ((select pass from cardinfo where cardid=@card) <> @inputpass )
begin
raiserror ('密码错误!',16,1)
return
end
insert into transinfo(transtype,cardid,transmoney) values(@type,@card,@m)
go
--2.调用存储过程取钱或存钱 张三取300,李四存500
----现实中的取款机依靠读卡器读出张三的卡号,这里根据张三的名字查出考号来模拟
declare @card char(19)
select @card=cardid
from cardinfo inner join userinfo
on cardinfo.customerid=userinfo.customerid
where customername='张三'
exec proc_takemoney @card,300 ,'支取','123456'
go
declare @card char(19)
select @card=cardid
from cardinfo inner join userinfo
on cardinfo.customerid=userinfo.customerid
where customername='李四'
exec proc_takemoney @card,500 ,'存入'
select * from view_cardinfo
select * from view_transinfo
go
--3.产生随机卡号的存储过程(一般用 当前月份数\当前秒数\当前毫秒数 乘以 一定的 系数 作为 随机种子)
--drop proc proc_randcardid
create procedure proc_randcardid
@randcardid char(19) output
as
declare @r numeric(15,8)
declare @tempstr char(10)
select @r = rand( (datepart(mm, getdate()) * 100000 )+ (datepart(ss, getdate()) * 1000 ) + datepart(ms, getdate()) )
set @tempstr = convert(char(10),@r) --产生0.xxxxxxxx的数字,我们需要小数点后的八位数字
set @randcardid = '1010 3576 ' + substring(@tempstr,3,4) + ' ' + substring(@tempstr,7,4) --组合为规定格式的卡号
go
--4.测试产生随机卡号
declare @mycardid char(19)
execute proc_randcardid @mycardid output
print '产生的随机卡号为:' + @mycardid
go
--5.开户的存储过程
-- drop proc proc_openaccount
create procedure proc_openaccount
@customername char(8),
@pid char(18),
@telephone char(13),
@openmoney money,
@savingtype char(8),
@address varchar(50) = ''
as
declare @mycardid char(19),@cur_customerid int
--调用产生随机卡号的存储过程获得随机卡号
execute proc_randcardid @mycardid output
while exists(select * from cardinfo where cardid = @mycardid)
begin
execute proc_randcardid @mycardid output
end
print '尊敬的客户,开户成功!系统为您产生的随机卡号为:' + @mycardid
print '开户日期' + convert(char(10),getdate(),111) + ' 开户金额:' + convert(varchar(20),@openmoney)
if not exists(select * from userinfo where pid = @pid) --给 用户信息表 填写用户开户信息
insert into userinfo(customername,pid,telephone,address) values(@customername,@pid,@telephone,@address)
select @cur_customerid = customerid from userinfo where pid = @pid
insert into cardinfo(cardid,savingtype,openmoney,balance,customerid) --给 用户卡信息表 填写用户开户信息
values(@mycardid,@savingtype,@openmoney,@openmoney,@cur_customerid)
go
--6.调用存储过程重新开户
exec proc_openaccount '王五','334456889012678','2222-63598978',1000,'活期','河南新乡'
exec proc_openaccount '赵二','213445678912342222','0760-44446666',1,'定期'
select * from cardinfo
select * from view_userinfo
select * from view_cardinfo
go
--=========================第五阶段====================================================================
/*$$$$$$$$$$$$$$$$$$$$$$事 务$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
--1.转帐的事务存储过程
create procedure proc_transfer
@card1 char(19), --李四 支出
@card2 char(19), --张三 存入
@outmoney money
as
begin tran
print '开始转帐,请稍后......'
declare @errors int
set @errors = 0
insert into transinfo(transtype,cardid,transmoney) values('支取',@card1,@outmoney)
set @errors = @errors + @@error
insert into transinfo(transtype,cardid,transmoney) values('存入',@card2,@outmoney)
set @errors = @errors + @@error
if (@errors>0)
begin
print '转帐失败!'
rollback tran
end
else
begin
print '转帐成功!'
commit tran
end
go
--2.测试上述事务存储过程
--从李四的帐户转帐2000到张三的帐户
--同上一样,现实中的取款机依靠读卡器读出张三/李四的卡号,这里根据张三/李四的名字查出考号来模拟
declare @card1 char(19),@card2 char(19)
select @card1 = cardid
from cardinfo inner join userinfo
on cardinfo.customerid=userinfo.customerid
where customername='李四'
select @card2 = cardid
from cardinfo inner join userinfo
on cardinfo.customerid=userinfo.customerid
where customername='张三'
--调用上述事务过程转帐
exec proc_transfer @card1,@card2,2000
--=========================================
select * from view_userinfo
select * from view_cardinfo
select * from view_transinfo
go
--=========================第六阶段====================================================================
/*$$$$$$$$$$$$$$$$$$$$$$安 全$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/
--1.添加sql登录帐号
if not exists(select * from master.dbo.syslogins where loginname='sysadmin')
begin
exec sp_addlogin 'sysadmin', '1234' --添加sql登录帐号
exec sp_defaultdb 'sysadmin' , 'bankdb' --修改登录的默认数据库为bankdb
end
go
--2.创建数据库用户
exec sp_grantdbaccess 'sysadmin', 'sysadmindbuser'
go
--3.--------给数据库用户授权
--为sysadmindbuser分配对象权限(增删改查的权限)
grant select,insert,update,delete,select on transinfo to sysadmindbuser
grant select,insert,update,delete,select on userinfo to sysadmindbuser
grant select,insert,update,delete,select on cardinfo to sysadmindbuser
go