图
书
借
阅
管
理
系
统
——数据库实践课程设计实验
注:图为word插入自带的,表格为excel表格先制作后复制粘贴到word的,代码为高亮处理后的代码块
目录
第一章 设计背景与需求分析
1.1 设计需求
1.2 设计背景
1.2.1 图书管理的现状
1.2.2 选题的目的、意义
1.3 系统开发环境
第二章 数据库概念结构设计
2.1 实体型结构
2.1.1 实体确定与分析
2.1.2 实体属性图
2.2 实体间的联系
2.2.1 实际条件(题设条件已经省略)
2.2.2 联系
第三章 数据库逻辑结构设计
3.1 E-R图向关系模式转换的原则
3.2 E-R图向关系模型的转化与关系模型的优化
3.2.1 模型优化概念
3.2.2 优化方法
3.2.3 模型优化后的关系模式图
3.3 视图结构
3.3.1 设计需求(1)视图
3.3.2 设计需求(2)视图
3.3.3 设计需求(3)视图
3.3.4 借阅次数前五的书视图
3.3.5 管理员操作记录视图
第四章 数据库物理结构设计
4.1 索引的设计原则
4.2 索引与视图的关系
4.3 索引结构设计
第五章 数据库实施
5.1 建表语句
5.1.1 出版社表
5.1.2 管理员表
5.1.3 读者表
5.1.4 书库表
5.1.5 书表
5.1.6 借阅表
5.1.7 存取表
5.2 建视图语句
5.2.1 视图1
5.2.2 视图2
5.2.3 视图3
5.2.4 借阅次数前五的书视图
5.2.5 管理员操作记录视图
5.3 索引
5.4 触发器
5.4.1 触发器——入库
5.4.2 触发器——借阅数据保护
5.4.3 触发器——借书
5.4.4 触发器——还款
5.4.5 触发器——还书
5.4.6 触发器——续借管理
第六章 测试数据
6.1 完整的测试数据
6.1.1 出版社
6.1.2 管理员
6.1.3 读者
6.1.4 书库
6.1.5 书
6.2 触发器测试
6.2.1 触发器——入库测试
6.2.2 触发器——借阅数据保护
6.2.3 触发器——借书测试
6.2.4 触发器——还款测试
6.2.5 触发器——还书测试
6.2.6 触发器——续借管理测试
6.3 测试视图
6.3.1 视图1测试
6.3.2 视图2测试
6.3.3 视图3测试
6.3.4 借阅次数前五的书测试
6.3.5 管理员操作记录测试
6.4 数据库操作管理
第七章 设计总结
7.1 遇到的主要问题和解决方法
7.2 进一步改进的设想
7.3 课程设计体会
7.4 学习数据库系统原理后的体会
第一章 设计背景与需求分析
1.1 设计需求
(1)可随时查询书库中现有书籍的品种、数量与存放位置。所有各类书籍均可由书号惟一标识。
(2)可随时查询书籍借还情况,包括借书人单位、姓名、借书证号、借书日期和还书日期。
我们约定:任何人可借多种书,任何一种书可为多个人所借,借书证号具有惟一性。
(3)当需要时,可通过数据库中保存的出版社的电报编号、电话、邮编及地址等信息向相应出版社增购有关书籍。我们约定,一个出版社可出版多种书籍,同一本书仅为一个出版社出版,出版社名具有惟一性。
1.2 设计背景
1.2.1 图书管理的现状
图书馆作为一种资源的集散地,图书和用户在借阅资料繁多,包含很多的信息管理,现在有很多的图书馆都是初步的开始使用,甚至尚未使用计算机进行资源管理,没有建立相对应的图书管理数据系统,而是使用人工计算,抄写进行,数据处理工作量大,容易出错和数据丢失。
1.2.2 选题的目的、意义
图书管理系统数据库有着手工管理无法比拟的优点,如检索迅速、查找方便、可靠性高、存储量大、保密性好,成本低等等。这些优点能极大提高图书管理的效率,因此,开发一套能够为用户提供充足的信息和快捷的查询手段的图书管理系统是十分必要的。
1.3 系统开发环境
1、系统:Windows10
2、开发平台:Microsoft SQL Server 2019
第二章 数据库概念结构设计
2.1 实体型结构
2.1.1 实体确定与分析
我们对题目进行了一段时间的分析,并在讨论后得出,此系统应该具备以下实体及属性。
实体与其属性对应如下:
读者:借书证号、姓名、性别、年龄、借书人单位
书:书号、书名、标价(损坏或丢失书籍时的赔偿价格)、作者、借阅次数
出版社:电报编号、出版社名字、地址、邮编、电话
书库:书库号、书籍的品种(即书库的分类大区)
管理员:管理员编号、姓名、性别
2.1.2 实体属性图
读者实体型
书实体型
出版社实体型
书库实体型
管理员实体型
2.2 实体间的联系
2.2.1 实际条件(题设条件已经省略)
我们假定:
一个管理员只管一个书库;每个书库位置分开,且读者借阅书籍时只能在书籍所属的书库登记;一个读者一次只能借阅一本书,即要归还前一本书才能借后一本书;一般入库书籍是5本,特殊情况更新存取表;
2.2.2 联系
1.一个出版社对应多本书,一个本书对应一个出版社,出版社和书是一对多联系。
2.读者、管理员和书三者之间是多对多的关系,即一个读者对应多本书,一个管理员对应不同书的读者,一本书对应多个读者。
3.一个书库对应多本书,一本书对应一个书库,书库和书之间是一对多联系。
4.一个管理员对应一个书库,一个书库对应一个管理员,管理员和书库之间是一对一联系。
2.3 E-R图
第三章 数据库逻辑结构设计
3.1 E-R图向关系模式转换的原则
1. 一个实体型转换为一个关系模式。
关系的属性:实体型的属性
关系的码:实体型的码
2.一个1:1联系可以转换为一个独立的关系模式,也可以与任何一端对应的关系模式合并。
3.一个1:n联系可以转换为一个独立的关系模式,也可以与n端对应的关系模式 合并。
4.一个m:n联系转换为一个关系模式。
5.三个或三个以上实体间的一个多元联系可以转换为一个关系模式。
6.具有相同码的关系模式可合并。
目的:减少系统中关系个数
7.同一实体集的实体之间的联系即自联系,也可以按1:1,1:n和m:n三种情况分别处理。
3.2 E-R图向关系模型的转化与关系模型的优化
3.2.1 模型优化概念
数据库逻辑设计的结果不是唯一的。为了进一步提高数据库应用系统的性能,还应该根据应用需要适当地修改、调整数据模型的结构,这就是数据模型的优化。
3.2.2 优化方法
1.确定数据依赖。
2.对于各个关系模式之间的数据依赖进行极小化处理,消除冗余的联系。
3.按照数据依赖的理论对关系模式逐一进行分析,考察是否存在部分函数依赖、传递函数依赖、多值依赖等,确定各关系模式分别属于第几范式。
4.根据需求分析阶段得到的处理要求分析对于这样的应用环境这些模式是否合适,确定是否要对某些模式进行合并或分解。
5.对关系模式进行必要分解,提高数据操作效率和存储空间利用率。常用的两种分解方法是水平分解和垂直分解。
3.2.3 模型优化后的关系模式图
3.2.3.1 出版社实体所对应的关系模式
列名(出版社) |
数据类型 |
长度 |
主键 |
非空 |
备注 |
电报编号 |
char |
10 |
Yes |
Yes |
|
出版社名称 |
varchar |
20 |
Yes |
||
地址 |
varchar |
20 |
Yes |
||
电话 |
char |
20 |
Yes |
||
邮编 |
char |
20 |
Yes |
3.2.3.2 管理员实体所对应的关系模式
列名(管理员) |
数据类型 |
长度 |
主键 |
非空 |
备注 |
管理员编号 |
int |
<=2 |
Yes |
Yes |
|
姓名 |
char |
10 |
Yes |
||
性别 |
char |
2 |
3.2.3.3 读者实体所对应的关系模式
列名(读者) |
数据类型 |
长度 |
主键 |
非空 |
备注 |
借书证号 |
int |
6 |
Yes |
Yes |
|
姓名 |
char |
10 |
Yes |
||
性别 |
char |
2 |
|||
年龄 |
int |
<=3 |
|||
借书人单位 |
varchar |
20 |
3.2.3.4 书实体所对应的关系模式
列名(书) |
数据类型 |
长度 |
主键 |
非空 |
备注 |
书号 |
int |
Yes |
Yes |
||
书名 |
char |
20 |
Yes |
||
标价 |
numeric(6,2) |
6 |
Yes |
||
作者 |
varchar |
10 |
Yes |
||
电报编号 |
char |
10 |
Yes |
外键,参照出版社表出版社编号 |
|
管理员编号 |
int |
<=2 |
Yes |
外键,参照管理员表的管理员编号 |
|
借阅次数 |
int |
Yes |
3.2.3.5 借阅关系所对应的关系模式
列名(借阅) |
数据类型 |
长度 |
主键 |
非空 |
备注 |
借书证号 |
int |
6 |
Yes |
Yes |
外键,读者表的借书证号 |
书号 |
int |
Yes |
Yes |
外键,参照书表的书号 |
|
管理员编号 |
int |
<=2 |
Yes |
Yes |
外键,参照管理员表的管理员编号 |
借书日期 |
datetime |
Yes |
|||
还书日期 |
datetime |
Yes |
|||
违规罚款 |
numeric(6,2) |
6 |
Yes |
||
续借 |
int |
1 |
Yes |
||
是否还款 |
char |
2 |
Yes |
||
是否还书 |
char |
2 |
Yes |
3.2.3.6 书库实体所对应的关系模式
列名(书库) |
数据类型 |
长度 |
主键 |
非空 |
备注 |
书库号 |
int |
<=2 |
Yes |
Yes |
|
书籍品种 |
char |
20 |
Yes |
||
管理员编号 |
int |
<=2 |
Yes |
外键,参照管理员表的管理员编号 |
3.2.3.7 存取关系所对应的关系模式
列名(存取) |
数据类型 |
长度 |
主键 |
非空 |
备注 |
书号 |
int |
Yes |
Yes |
外键,参照书表的书号 |
|
存取位置 |
int |
<=2 |
Yes |
Yes |
外键,参照书库表的书库号 |
存取数量 |
int |
Yes |
|||
可借数量 |
int |
Yes |
3.3 视图结构
3.3.1 设计需求(1)视图
列名 |
来源表 |
书库号 |
书库表 |
书籍品种 |
书库表 |
存取位置 |
存取表 |
数量 |
存取表(每个书库各书数量之和) |
3.3.2 设计需求(2)视图
列名 |
来源表 |
借书日期 |
借阅表 |
姓名 |
读者表 |
借书证号 |
借阅表 |
借书人单位 |
读者表 |
还书日期 |
借阅表 |
3.3.3 设计需求(3)视图
列名 |
来源表 |
编号 |
出版社表 |
电话 |
出版社表 |
邮编 |
出版社表 |
地址 |
出版社表 |
3.3.4 借阅次数前五的书视图
列名 |
来源表 |
书号 |
书表 |
书名 |
书表 |
借阅次数 |
书表 |
3.3.5 管理员操作记录视图
列名 |
来源表 |
借书证号 |
借阅表 |
姓名 |
读者表 |
借书日期 |
借阅表 |
还书日期 |
借阅表 |
是否还书 |
借阅表 |
本次操作人编号 |
借阅表 |
第四章 数据库物理结构设计
4.1 索引的设计原则
(1)如果一个(或一组)属性经常在查询条件中出现,则考虑早这个(或这组)属性建立索引。
(2)如果一个属性经常作为最大值和最小值等聚集函数的参数,则考虑这个属性上建立索引。
(3)如果一个(或一组)属性经常在连接操作的连接条件中出现,则考虑在这个(或这组)属性上建立索引。
4.2 索引与视图的关系
视图是通过索引查询表而的出结果的,表建立了索引,查询速度会提高
索引:在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。
视图:数据库中的视图,是一个虚拟表,其内容由查询定义。
4.3 索引结构设计
表名 |
索引名 |
索引列 |
书 |
书号索引 |
书号 |
书 |
书名索引 |
书名 |
书 |
借阅次数索引 |
借阅次数 |
读者 |
姓名索引 |
姓名 |
读者 |
借书人单位索引 |
借书人单位 |
书库 |
书库号索引 |
书库号 |
书库 |
书籍品种索引 |
书籍品种 |
出版社 |
电报编号索引 |
电报编号 |
出版社 |
电话索引 |
电话 |
出版社 |
邮编索引 |
邮编 |
出版社 |
地址索引 |
地址 |
存取 |
存取位置索引 |
存取位置 |
存取 |
存取数量索引 |
存取数量 |
借阅 |
借书证号索引 |
借书证号 |
借阅 |
书号索引 |
书号 |
借阅 |
管理员编号索引 |
管理员编号 |
借阅 |
借书日期索引 |
借书日期 |
借阅 |
还书日期索引 |
还书日期 |
借阅 |
违规罚款索引 |
违规罚款 |
借阅 |
续借索引 |
续借 |
借阅 |
是否还款索引 |
是否还款 |
第五章 数据库实施
5.1 建表语句
5.1.1 出版社表
--出版社表-1
create table 出版社(
电报编号 char(10) primary key,--主键
出版社名称 varchar(20) not null,
地址 varchar(20) not null,
电话 char(20) not null unique,
邮编 char(20) not null
)
go
--调试(记录会在正式测试时清除)
insert into 出版社(电报编号,出版社名称,地址,电话,邮编) values('000','测试','养根楼','173821068830','417000')
select * from 出版社
5.1.2 管理员表
--管理员表-2
create table 管理员(
--管理员离职更新名字、性别即可
管理员编号 int identity(1,1) check(len(管理员编号)<=2) primary key,
--主键;管理员编号初始值为1,递加也为1
姓名 char(10) not null,
性别 char(2) check (性别 in ('男','女'))
)
go
--调试(记录会在正式测试时清除)
insert into 管理员(姓名,性别) values('刘志强','男')
delete from 管理员 where 管理员编号=1
select * from 管理员
5.1.3 读者表
--读者表-3
create table 读者(
借书证号 int identity(220000,1) check(len(借书证号)<230000) primary key,--主键;借书证号初始值为220000,递加也为1
姓名 char(10) not null,--220000前两位为年份可自己修改
性别 char(2) check (性别 in ('男','女')),
年龄 int check (len(年龄)<=3),
借书人单位 varchar(20),
)
go
--调试(记录会在正式测试时清除)
insert into 读者(姓名,性别,年龄,借书人单位) values('刘志强','男',21,'湖南人文科技学院')
delete from 读者 where 借书证号=220001
select * from 读者
5.1.4 书库表
--书库表-4
create table 书库(
书库号 int check(len(书库号)<=2) primary key,--主键
书籍品种 char(20)unique not null,
管理员编号 int not null,--外键--保证一个管理员管一个书库
check(书库号=管理员编号),--保证一个管理员管一个书库
foreign key(管理员编号) references 管理员(管理员编号)
)
go
--调试(记录会在正式测试时清除)
insert into 书库(书库号,书籍品种,管理员编号) values(1,'sdd54ss',1)
delete from 书库 where 书库号=6
select * from 书库
5.1.5 书表
--书表-5
create table 书(
书号 int identity(1,1) primary key,
--主键;书号初始值为1,递加也为1
书名 char(20) not null,
标价 numeric(6,2) not null,
作者 varchar(10) not null,
电报编号 char(10) not null,--外键
管理员编号 int,--外键
借阅次数 int default 0,--初始值默认为0
foreign key(电报编号) references 出版社(电报编号),
foreign key(管理员编号) references 管理员(管理员编号)
)
go
--调试(记录会在正式测试时清除)
insert into 书(书名,标价,作者,电报编号,管理员编号) values('数据库',99.99,'xxx','000',1)
delete from 书 where 书号=1
select * from 书
5.1.6 借阅表
--借阅表-6
create table 借阅(
借书证号 int,--主属性、外键
书号 int,--主属性、外键
管理员编号 int,
借书日期 datetime default getdate(),
--主属性;借书日期为系统时间
还书日期 datetime default dateadd(day,7,getdate()),
--第一次借书还书日期为七天后,可提前还书
违规罚款 numeric(6,2) default 0,
--罚款金额长度为6,精度为2,默认数值为0
续借 int default 0 check (续借<=4),
--每次续借可多借7天,最多续借4次,默认0次
是否还款 char(2) default '是' check (是否还款 in ('是','否')),
--借书时默认为'是'
是否还书 char(2) default '否' check (是否还书 in ('是','否')),
--借书时默认填否,还书时改回来
check(还书日期>=借书日期),--保证还书日期小于借书日期
primary key(借书证号,书号,借书日期),
foreign key(借书证号) references 读者(借书证号)on delete cascade on update cascade,--级联删除、更新
foreign key(书号) references 书(书号)on delete cascade on update cascade,--级联删除、更新
foreign key(管理员编号) references 管理员(管理员编号)
)
go
--调试(记录会在正式测试时清除)
insert into 借阅(借书证号,书号,管理员编号) values(220000,6,1)
update 借阅
set 是否还款='是'
where 借书证号=220000
select * from 借阅
update 借阅
set 是否还书='是'
where 借书证号=220000 and 书号=6
update 借阅
set 续借=1
where 借书证号=220002 and 书号=4
5.1.7 存取表
--存取表-7
create table 存取(
书号 int,--主属性、外键
存取位置 int,--主属性、外键
存取数量 int default 5 not null,--本系统一般存5本书,非5时可修改
可借数量 int default 5 check (可借数量>=0) not null,
check (可借数量<=存取数量),--0<=可借数量<=存取数量 限制可借数量在合理范围内
primary key(书号,存取位置),
foreign key(存取位置) references 书库(书库号),
foreign key(书号) references 书(书号)on delete cascade on update cascade,--级联删除、更新
)
go
--调试(记录会在正式测试时清除)
insert into 存取(书号,存取位置) values(2,1)
select * from 存取
5.2 建视图语句
5.2.1 视图1
--视图1
create view 视图1(书库号,书籍品种,存取位置,数量)
as
select 书库号,书籍品种,存取位置,sum(存取数量)
from 书库,存取
where 存取位置=书库号
group by 书库号,书籍品种,存取位置
go
--配套查询语句
select * from 视图1
5.2.2 视图2
--视图2
create view 视图2(借书日期,姓名,借书证号,借书人单位,还书日期)
as
select 借书日期,姓名,借阅.借书证号,借书人单位,还书日期
from 借阅 left outer join 读者 on(借阅.借书证号=读者.借书证号)
go
--配套查询语句
select * from 视图2 order by 借书日期 desc
5.2.3 视图3
--视图3
create view 视图3(编号,电话,邮编,地址)
as
select 电报编号,电话,邮编,地址
from 出版社
go
--配套查询语句
select * from 视图3
5.2.4 借阅次数前五的书视图
--借阅次数前五的书视图
create view 借阅次数前五的书(书号,书名,借阅次数)
as
select top(5) 书号,书名,借阅次数
from 书
where 借阅次数>0
order by 借阅次数 desc
go
--配套查询语句
select * from 借阅次数前五的书
5.2.5 管理员操作记录视图
--管理员操作记录视图
create view 管理员操作记录(借书证号,姓名,借书日期,还书日期,是否还书,本次操作人编号)
as
select 借阅.借书证号,读者.姓名,借阅.借书日期,借阅.还书日期,借阅.是否还书,借阅.管理员编号
from 借阅 left outer join 读者 on(借阅.借书证号=读者.借书证号)
go
--配套查询语句
select * from 管理员操作记录 order by 借书日期 desc
5.3 索引
--索引
--drop index 借阅次数索引 on 书;
create index 书号索引 on 书(书号);
create index 书名索引 on 书(书名);
create index 借阅次数索引 on 书(借阅次数);
create index 姓名索引 on 读者(姓名);
create index 借书人单位索引 on 读者(借书人单位);
create index 书库号索引 on 书库(书库号);
create index 书籍品种索引 on 书库(书籍品种);
create index 电报编号索引 on 出版社(电报编号);
create index 电话索引 on 出版社(电话);
create index 邮编索引 on 出版社(邮编);
create index 地址索引 on 出版社(地址);
create index 存取位置索引 on 存取(存取位置);
create index 存取数量索引 on 存取(存取数量);
create index 借书证号索引 on 借阅(借书证号);
create index 书号索引 on 借阅(书号);
create index 管理员编号索引 on 借阅(管理员编号);
create index 借书日期索引 on 借阅(借书日期);
create index 还书日期索引 on 借阅(还书日期);
create index 违规罚款索引 on 借阅(违规罚款);
create index 续借索引 on 借阅(续借);
create index 是否还款索引 on 借阅(是否还款);
5.4 触发器
5.4.1 触发器——入库
--入库---1
--当入库新书时,书表改变,存取表也需要添加数据
create trigger 入库 on 书
for insert as
declare @新书书号 int,@新书分管人 int
select @新书书号=书号,@新书分管人=管理员编号 from inserted
begin
insert into 存取(书号,存取位置) values(@新书书号,@新书分管人)--管理员号和存取位置是一致的,因为一个管理员管一个书库
end
5.4.2 触发器——借阅数据保护
--借阅数据保护---2
create trigger 借阅数据保护 on 借阅 --借阅表不允许delete操作
for delete as
raiserror('借阅表数据不允许删除!',16,1)
rollback
5.4.3 触发器——借书
--借书---3
--insert into 借阅(借书证号,书号,管理员编号) values(220000,1,1)
create trigger 借书 on 借阅
for insert as --笔记:在触发器执行时,触发器所对的被操作表 等于 之前操作的所有数据加刚刚操作的数据
declare @未还书数量 int,@借书证号 int,@所借书号 int,@此次借书日期 datetime
begin
select @借书证号=借书证号,@所借书号=书号,@此次借书日期=借书日期 from inserted
select @未还书数量=count(是否还书) from 借阅 where 借书证号=@借书证号 and 是否还书='否'
end
if '否' in (select 是否还款 from 借阅 where 借书证号=@借书证号)--欠款未交
begin
raiserror('请先交齐罚款!',16,1)
rollback
end
else if @所借书号 in (select 书号 from 借阅 where 借书日期!=@此次借书日期 and 书号=@所借书号 and 借书证号=@借书证号 and 是否还书='否')
--同本书一人只能借一次
begin
raiserror('同本书一人只能借一次!',16,1)
rollback
end
else if @未还书数量>3--借了3本书还没还
begin
select * from 借阅
raiserror('已借书3本,无法再借!',16,1)
rollback
end
else--成功插入后需进行以下操作
begin
update 书
set 借阅次数=借阅次数+1
where 书号=@所借书号
update 存取
set 可借数量=可借数量-1
where 书号=@所借书号
end
5.4.4 触发器——还款
--还款---4
create trigger 还款 on 借阅
for update as
declare @新是否还款 char(2),@旧是否还款 char(2),@借书证号 int,@所借书号 int,@此次借书日期 datetime
select @新是否还款=是否还款,@借书证号=借书证号,@所借书号=书号,@此次借书日期=借书日期 from inserted
select @旧是否还款=是否还款 from deleted
if update(是否还款)--此列更新都会进入此触发器
begin
if @新是否还款=@旧是否还款 and @旧是否还款='是'
begin
raiserror('此书欠款已还清!',16,1)
rollback
end
else if @旧是否还款='否' and @新是否还款='是'
begin
update 借阅
set 违规罚款=0
where 借书证号=@借书证号 and 书号=@所借书号 and 借书日期=@此次借书日期
end
end
5.4.5 触发器——还书
--还书---5
create trigger 还书 on 借阅
for update as
declare @新是否还书 char(2),@旧是否还书 char(2),@借书证号 int,@所借书号 int,@此次借书日期 datetime,@旧还书日期 datetime
select @新是否还书=是否还书,@借书证号=借书证号,@所借书号=书号,@此次借书日期=借书日期 from inserted
select @旧是否还书=是否还书,@旧还书日期=还书日期 from deleted
if update(是否还书)--此列更新都会进入此触发器
begin
if @新是否还书=@旧是否还书 and @旧是否还书='是'
begin
raiserror('此书已还!',16,1)
rollback
end
else if @旧还书日期
5.4.6 触发器——续借管理
--续借管理---6
create trigger 续借管理 on 借阅
for update as
declare @新是否还书 char(2),@旧是否还书 char(2),@借书证号 int,@所借书号 int,@还书日期 datetime,@此次借书日期 datetime
select @新是否还书=是否还书,@借书证号=借书证号,@所借书号=书号 from inserted
select @旧是否还书=是否还书,@还书日期=还书日期,@此次借书日期=借书日期 from deleted
if update(续借)--此列更新都会进入此触发器
begin
if @新是否还书=@旧是否还书 and @旧是否还书='是'
begin
raiserror('此书已还,无法续借!',16,1)
rollback
end
else if @新是否还书=@旧是否还书 and @旧是否还书='否'
begin
update 借阅
set 还书日期=dateadd(day,7,@还书日期)
where 借书证号=@借书证号 and 书号=@所借书号 and 借书日期=@此次借书日期
end
end
第六章 测试数据
6.1 完整的测试数据
6.1.1 出版社
--出版社
insert into 出版社(电报编号,出版社名称,地址,电话,邮编) values('00-01','娄底出版社','娄底','010-58565118','417000')
insert into 出版社(电报编号,出版社名称,地址,电话,邮编) values('00-02','衡阳出版社','衡阳','041-68934658','421001')
insert into 出版社(电报编号,出版社名称,地址,电话,邮编) values('00-03','长沙出版社','长沙','031-52635632','410013')
insert into 出版社(电报编号,出版社名称,地址,电话,邮编) values('00-04','邵阳出版社','邵阳','037-55699988','422000')
insert into 出版社(电报编号,出版社名称,地址,电话,邮编) values('00-05','株洲出版社','株洲','054-85698752','412000')
insert into 出版社(电报编号,出版社名称,地址,电话,邮编) values('00-06','云南出版社','云南','079-68855832','650000')
6.1.2 管理员
--管理员
insert into 管理员(姓名,性别) values('刘志强','男')
insert into 管理员(姓名,性别) values('黄平','男')
insert into 管理员(姓名,性别) values('洪宁','男')
insert into 管理员(姓名,性别) values('余家荣','男')
insert into 管理员(姓名,性别) values('王香兰','女')
6.1.3 读者
--读者表
insert into 读者(姓名,性别,年龄,借书人单位) values('罗凯','男',20,'湖南人文科技学院')
insert into 读者(姓名,性别,年龄,借书人单位) values('叶博宇','男',19,'湖南人文科技学院')
insert into 读者(姓名,性别,年龄,借书人单位) values('蒋杰','男',21,'湖南人文科技学院')
insert into 读者(姓名,性别,年龄,借书人单位) values('陈晗','男',22,'湖南人文科技学院')
insert into 读者(姓名,性别,年龄,借书人单位) values('宇智波佐助','男',20,'火影忍者')
insert into 读者(姓名,性别,年龄,借书人单位) values('日向雏田','女',19,'火影忍者')
insert into 读者(姓名,性别,年龄,借书人单位) values('丁真','男',21,null)
6.1.4 书库
--书库
insert into 书库(书库号,书籍品种,管理员编号) values(1,'教辅类',1)
insert into 书库(书库号,书籍品种,管理员编号) values(2,'经济学类',2)
insert into 书库(书库号,书籍品种,管理员编号) values(3,'小说类',3)
insert into 书库(书库号,书籍品种,管理员编号) values(4,'游戏教程类',4)
insert into 书库(书库号,书籍品种,管理员编号) values(5,'自然科学类',5)
6.1.5 书
--书
insert into 书(书名,标价,作者,电报编号,管理员编号) values('数据库原理设计',25.00,'王珊','00-01',1)
insert into 书(书名,标价,作者,电报编号,管理员编号) values('操作系统与linux设计',38.00,'申丰山','00-03',1)
insert into 书(书名,标价,作者,电报编号,管理员编号) values('大学英语',69.90,'郑树棠','00-05',1)
insert into 书(书名,标价,作者,电报编号,管理员编号) values('毛泽东思想概论',25.00,'王伟光','00-01',1)
insert into 书(书名,标价,作者,电报编号,管理员编号) values('经济学',120.56,'兹维博迪','00-04',2)
insert into 书(书名,标价,作者,电报编号,管理员编号) values('投资学',140.29,'兹维博迪','00-01',2)
insert into 书(书名,标价,作者,电报编号,管理员编号) values('经济发展规律',243.89,'巴菲克','00-01',2)
insert into 书(书名,标价,作者,电报编号,管理员编号) values('虚拟货币',620.00,'黄sir','00-04',2)
insert into 书(书名,标价,作者,电报编号,管理员编号) values('金瓶梅',98.96,'王世贞','00-01',3)
insert into 书(书名,标价,作者,电报编号,管理员编号) values('十八摸',78.36,'黄sir','00-04',3)
insert into 书(书名,标价,作者,电报编号,管理员编号) values('霸道总裁爱上我',20.00,'洪sir','00-03',3)
insert into 书(书名,标价,作者,电报编号,管理员编号) values('都市传奇',20.00,'黄sir','00-04',3)
insert into 书(书名,标价,作者,电报编号,管理员编号) values('射击游戏教程',34.69,'aou君','00-05',4)
insert into 书(书名,标价,作者,电报编号,管理员编号) values('赛马娘教程攻略',34.69,'aou君','00-05',4)
insert into 书(书名,标价,作者,电报编号,管理员编号) values('二次元游戏的那些事',34.69,'aou君','00-05',4)
insert into 书(书名,标价,作者,电报编号,管理员编号) values('火影忍者游戏攻略',34.69,'呆某','00-02',4)
insert into 书(书名,标价,作者,电报编号,管理员编号) values('小蝌蚪找妈妈',34.69,'王某人','00-06',5)
insert into 书(书名,标价,作者,电报编号,管理员编号) values('狗子刨坑',34.69,'黄sir','00-04',5)
insert into 书(书名,标价,作者,电报编号,管理员编号) values('蜻蜓点水',34.69,'洪sir','00-03',5)
insert into 书(书名,标价,作者,电报编号,管理员编号) values('植物是怎么睡觉的',34.69,'aou君','00-05',5)
6.2 触发器测试
首先查看数据库导入的表数据:
6.2.1 触发器——入库测试
功能:书表插入数据后,自动填写存取表,存取数量和可借数量都默认为5,用户想修改也是可以修改的。
经过上面数据导入之后,我们查询存取表,结果如下:
很明显,该触发器功能已实现。
6.2.2 触发器——借阅数据保护
功能:保护借阅数据不能被删除(delete)
插入数据并查询:
insert into 借阅(借书证号,书号,管理员编号) values(220000,6,1)
此时进行delete操作:
很明显,该触发器功能已实现。
6.2.3 触发器——借书测试
功能:
1.欠款未交----事务回滚
2.违反同本书一人只能借一次----事务回滚
3.借了3本书还没还----事务回滚
4.成功插入后需进行以下操作----update书的借阅次数+1
update存取的可借数量-1
首先更新此人为欠款的人:
我们发现其可以还书,
但是不能借书,必须先交罚款
此时,我们再看一下书表和存取表的变化:
由于是借了书所以借阅次数+1,但是刚刚进行过还书。
此时我们让220000读者再借两次同本书。首先还款,
第一次借书号=6的书:
还书后再次借书成功
第二次借书:
同一人只能借同一本书一本
然后我们再让220000读者借3本书
很明显,书号1=9的书没借成功,因为一个人最多借三本书
因此,此触发器实现完成。
6.2.4 触发器——还款测试
功能:
1.已经还清的人再还款----回滚事务
2.还款----罚款清0
修改数据,使其违规罚款=10
此时进行还款操作
我们发现还款清0了,且也已还款
经测试发现该触发器良好。
6.2.5 触发器——还书测试
功能:
1.已经还书还还书----回滚事务
2.还书太晚----罚款
3.还书成功----update借阅表此次借阅的还书日期
update存取表的可借数量+1
验证如下:
此时,我们再次让220000还这本书
还书太晚就会出现下面的情况,虽然还是还了但是罚款
220001读者借了7号书,预计还书日期是2022-5-14 3:38:00
结果还书晚了一分钟,就罚款了
经过测试基本可行。
6.2.6 触发器——续借管理测试
功能:
1.书已经还了----回滚事务
2.续借----实现续借后借书日期和还书日期的自动更新(一次续借+7天)
我们让220000读者续借7号书,可以发现还书日期和续借的改变
我们再让220000读者续借6号书,6号书他已经还了,所以续借不了
续借次数是不能大于4的,这是一开始建表用户定义的完整性
总的来说,此触发器符合预期。
6.3 测试视图
6.3.1 视图1测试
可随时查询书库中现有书籍的品种、数量与存放位置。所有各类书籍均可由书号惟一标识。
6.3.2 视图2测试
可随时查询书籍借还情况,包括借书人单位、姓名、借书证号、借书日期和还书日期。
6.3.3 视图3测试
当需要时,可通过数据库中保存的出版社的电报编号、电话、邮编及地址等信息向相应出版社增购有关书籍。
6.3.4 借阅次数前五的书测试
查看借阅次数前5的书,不是前五不用查,且按降序排列
6.3.5 管理员操作记录测试
查询管理员的操作记录,且按时间大小降序排列
6.4 数据库操作管理
下面给管理员提供快捷的操作方式:
--插入数据管理:
--管理员导入数据业务时的操作
--1--出版社表数据导入形式如下:
insert into 出版社(电报编号,出版社名称,地址,电话,邮编) values('000','测试','养根楼','173821068830','417000')
--2--管理员表数据导入形式如下:
insert into 管理员(姓名,性别) values('刘志强','男')
--3--读者表数据导入形式如下:
insert into 读者(姓名,性别,年龄,借书人单位) values('刘志强','男',21,'湖南人文科技学院')
--4--书库表数据导入形式如下:
insert into 书库(书库号,书籍品种,管理员编号) values(1,'sdd54ss',1)
--5--书表数据导入形式如下:
insert into 书(书名,标价,作者,电报编号,管理员编号) values('数据库',99.99,'xxx','000',1)
--------------------------------------------------------------------------------------------------
--管理员处理读者借书业务的操作
--1--读者借书操作形式如下:
insert into 借阅(借书证号,书号,管理员编号) values(220000,6,1)
select * from 借阅
delete from 借阅 where 借书证号=220000 and 书号=6
--2--读者借书发现自己欠款:
select * from 借阅 where 借书证号=220000 and 书号=6 and 是否还款='否'
--此时再进行后面的 管理员处理读者还书、还款业务的操作2
--------------------------------------------------------------------------------------------------
--管理员处理读者还书、还款业务的操作
--1--读者还书操作形式如下:
declare @借书日期 datetime
select @借书日期=max(借书日期) from 借阅 where 借书证号=220000 and 书号=6
update 借阅
set 是否还书='是'
where 借书证号=220000 and 书号=6 and 借书日期=@借书日期
--2--读者还款操作形式如下:
declare @借书日期 datetime
select @借书日期=max(借书日期) from 借阅 where 借书证号=220000 and 书号=6
update 借阅
set 是否还款='是'
where 借书证号=220000 and 书号=6 and 借书日期=@借书日期
--3--读者还款加还书
declare @借书日期 datetime
select @借书日期=max(借书日期) from 借阅 where 借书证号=220000 and 书号=6
update 借阅
set 是否还书='是',是否还款='是'
where 借书证号=220000 and 书号=6 and 借书日期=@借书日期
--------------------------------------------------------------------------------------------------
--管理员处理读者续借业务的操作
--1--读者续借书籍
declare @借书日期 datetime
select @借书日期=max(借书日期) from 借阅 where 借书证号=220000 and 书号=6
update 借阅
set 续借=4
where 借书证号=220000 and 书号=6 and 借书日期=@借书日期
第七章 设计总结
7.1 遇到的主要问题和解决方法
1.在讨论这个E-R图时出现了一些分歧,但是经过细致的讨论和分析,最终我们从理论上选择了现在的E-R图模型;
2.其次我在写代码时,发现了触发器的设置很容易出现触发器之间的冲突,最后我们合理运用分类的方法。首先按表给触发器分类,同表再按不同操作分类,最坏的情况是几个触发器的触发条件都是对一个表是更新操作,此时需要去考虑集合包含之间的关系,将条件卡死,最终我得到了不起冲突的6个触发器;
3.在之前表的结构还是有些问题的,由于判断失误,借阅表我们选择了借书证号、书号、管理员号做主码,这给我们前期造成了不小的麻烦,但是后面我将借阅的主码定位借书证号、书号、结束时间解决了这个问题;
4.其次是触发器设计代码实现时我遇到的问题,就是在触发器内进行该表查询时,该表的数据应该是之前的加上刚刚操作的,即使事务最后被回滚了也是能查询到的,但是回滚后再在触发器外单独查询将查不到回滚事务去掉的那条数据,这给我很大启示,使得我做触发器时选择更加灵活多变;
7.2 进一步改进的设想
该图书借阅管理系统还存在着许多问题,在逻辑结构设计的过程中一些表虽然减少了冗余,但在查询使用的过程中却存在着语句复杂,使用复杂的问题。同时用于实时检验和修改的触发器设计过于简陋,触发器数量太少,使得该系统不太成熟。
7.3 课程设计体会
通过对图书借阅管理系统的设计,一方面让我们组明白了数据库原理在图书管理上运用的流程,另一方面也让我们再次熟悉SQL-server 2019的开发工具的使用方法,了解了SQL建立数据库的一系列过程。在课程设计的过程中也遇到了一些问题,但是通过请教老师和同组同学讨论,解决了不少问题,对数据库系统原理也用了一个体系化的理解,收获很大。
7.4 学习数据库系统原理后的体会
数据库的使用和高级程序开发的关系密不可分,学好数据库系统原理对于进一步理解程序设计流程和软件开发应用有着很大作用,通过本学期数据库系统原理的学习,虽然现在还没有真正使用数据库和高级语言一起用于程序的开发,但对开发流程和其中用到的数据库原理已经有所理解了。
注:本系统并不完善,仅仅为期末的课程设计