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



    

posted on 2016-09-08 20:58  波波嘟  阅读(171)  评论(0编辑  收藏  举报