--=========================第一阶段==================================================================== /*$$$$$$$$$$$$$ 创建文件夹 $$$$$$$$$$$$$$$$$$*/ 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