图书馆作为一种资源的集散地,图书和用户在借阅资料繁多,包含很多的信息管理,现在有很多的图书馆都是初步的开始使用,甚至尚未使用计算机进行资源管理,没有建立相对应的图书管理数据系统,而是使用人工计算,抄写进行,数据处理工作量大,容易出错和数据丢失。
1.2.2选题的目的、意义
图书管理系统数据库有着手工管理无法比拟的优点,如检索迅速、查找方便、可靠性高、存储量大、保密性好,成本低等等。这些优点能极大提高图书管理的效率,因此,开发一套能够为用户提供充足的信息和快捷的查询手段的图书管理系统是十分必要的。
1.2.1读者信息的增加、修改、删除等基本操作
1.读者类别信息的输入,包括图书类型、图书册数等
2.读者档案信息的输入,包括读者编号、读者类型等
1.2.2图书信息的增加、修改、删除等基本操作。
1.图书类别信息的输入,包括类别编号,类别名称等。
2.图书类别信息的查询,修改,包括类别编号,类别名称等。
3.图书档案信息的输入,包括图书编号,图书名称,图书类别,作者名称,出版社名称,出版日期,图书页数,关键词,登记日期,备注信息等。
1.2.3图书流通管理
1.图书征订管理
2.图书借阅管理
3.图书归还管理
4.图书罚款管理
1、系统:WindowsXP,7,8,10
2、开发平台:SQLSERVER2070,VISUALBASIC6.0
SQLSERVER2017是一个关系数据管理系统,是微软公司推出的新版本,该版本增加了许多先进的功能,具有方便使用,可伸缩性好与软件集成度高等的优点,可以运行在个人电脑到大型多处理器的服务器等多种平台使用。
1.一个出版社对应多个图书,一个图书对应一个出版社,出版社和图书是一对多联系。
2.一个图书类型对应多个图书,一个图书对应一个图书类型,图书类型和图书是一对多联系。
3.一个读者类型对应多个读者,一个读者对应一个读者类型,读者类型和读者是一对多联系。
4.一个书库对应多个图书类型,一个图书类型对应一个书库,书库和图书类型是一对多联系。
5.一个图书入库单对应多个图书入库单明细,一个图书入库单明细对应一个图书入库单,图书入库单和图书入库单明细是一对多联系。
6.一个图书报损单对应多个图书报损单明细,一个图书报损单明细对于一个图书报损单,图书报损单和图书报损单明细是一对多联系。
7.一个读书对应多个图书入库单明细,一个图书入库单明细对应一个图书,图书和图书入库单明细是一对多联系。
8.一个读书对应多个图书报损单明细,一个图书报损单明细对应一个图书,图书和图书报损单明细是一对多联系。
9.一个读者对应多个罚款交费单,一个罚款交罚单对应一个读者,读者和罚款交费单是一对多联系。
10.一个职工对应多个图书入库单,一个图书入库单对应一个职工,职工和图书入库单是一对多联系。
11.一个职工对应多个图书报损单,一个图书报损单对应一个职工,职工和图书报损单是一对多联系。
12.一个职工对应多个罚款交费单,一个罚款交费单对应一个职工,职工和罚款交费单是一对多联系。
13.一个读者对应多个图书,一个图书对应多个读者,读者和图书之间是多对多联系。
1.一个实体型转换为一个关系模式。
关系的属性:实体型的属性
关系的码:实体型的码
2.一个1:1联系可以转换为一个独立的关系模式,也可以与任何一端对应的关系模式合并。
3.一个1:n联系可以转换为一个独立的关系模式,也可以与n端对应的关系模式合并。
4.一个m:n联系转换为一个关系模式。
5.三个或三个以上实体间的一个多元联系可以转换为一个关系模式。
6.具有相同码的关系模式可合并。
目的:减少系统中关系个数
7.同一实体集的实体之间的联系即自联系,也可以按1:1,1:n和m:n三种情况分别处理。
表3.1出版社表
列名
数据类型
长度
主键
非空
备注
出版社编号
Int
Yes
出版社名称
Varchar
50
出版社地址
表3.2图书表
图书编号
varchar
20
外码,参照出版表出版社编号
图书类型编号
char
1
外码,参照图书类型表,图书类型编号
书名
作者
价格
Numeric(8,2)
页码
库存总量
现存量
Datetime
借出次数
表3.3图书类型表
Char
”
图书类型名
书库号
int
外码,参照书库表的书库号
表3.4读者表
证书编号
读者类型编号
10
外码,参照读者类型表的读者类型编号
姓名
性别
只能为“男”、或“女”
出生日期
身份证编号
18
必须是18位
图书借阅次数
是否挂失
0未挂失
1已挂失
已借册数
未交罚款金额
表3.5读者类型表
读者类型名
vachar
可借阅册数
有效范围是20---60
借期天数
有效范围是90---120
可续借天数
有效范围是10---60
表3.6书库表
书库名
varchat
表3.7职工表
职工编号
职工姓名
文化程度
表3.8罚款交费单表
交费单号
借书证编号
外码,参照读者表证书编号
日期
金额
表3.9图书入库单表
入库编号
入库日期
经手职工编号
外码,参照职工表的职工编号
是否入库
0已入库
1未入库
表3.10图书入库单明细表
图书入库单编号
报损单编号和图书编号一起作为主码
外码,参照图书入库单表的图书入库编号
外码,参照图书表的图书编号
数量
表3.11图书报损单表
报损单编号
报损日期
经手人编号
表3.12图书报损单明细
图书报损单编号
外码,参照图书报损单表的报损单编号
报损原因
100
表3.13借阅表
借书证编号和图书编号一起作为主码
外码,参照读者表的证书编号
借书日期
还书日期
还书日期>=借书日期
罚款金额
Numeric(8,2)
是否续借
0未续借
1已续借
3.3.1入库单视图
入库单编号
图书入库单表
经手人姓名
职工表
是否已入库
图书入库单明细表
图书表
出版社名
出版社表
入库数量
表3.3.2报损单视图
图书报损单表
图书报损单明细表
报损数量
表3.3.3读者未还借书视图
借阅表
读者姓名
读者表
未还书编号
未还书名
可借期天数
读者类型表
表3.3.4图书分类库存视图
图书类型表
库存册数合计
库存金额合计
表3.3.5借出次数前100图书视图
(1)如果一个(或一组)属性经常在查询条件中出现,则考虑早这个(或这组)属性建立索引。
(2)如果一个属性经常作为最大值和最小值等聚集函数的参数,则考虑这个属性上建立索引。
(3)如果一个(或一组)属性经常在连接操作的连接条件中出现,则考虑在这个(或这组)属性上建立索引。
表4.1索引结构表
表名
索引名
索引列
备注(索引的设计理由)
图书
书名索引
经常查询的列
出版社编号索引
出版编社号
经常连接的列
图书类型索引
作者索引
图书类型
书库号索引
读者
姓名索引
图书借阅次数索引
聚集函数的参数
已借册数索引
未交罚款金额索引
职工
罚款交费单
借书证编号索引
图书入库单
经手职工编号索引
图书入库单明细
图书入库单编号索引
图书编号索引
图书报损单
图书报损单明细
图书报损单编号索引
借阅
CREATEINDEX书名索引ON图书(书名);CREATEINDEX出版社编号索引ON图书(出版社编号);CREATEINDEX图书类型编号索引ON图书(图书类型编号);CREATEINDEX作者索引ON图书(作者);CREATEINDEX书库号索引ON图书类型(书库号);CREATEINDEX姓名索引ON读者(姓名);CREATEINDEX图书借阅次数索引ON读者(图书借阅次数);CREATEINDEX已借册数索引ON读者(已借册数);CREATEINDEX未交罚款金额索引ON读者(未交罚款金额);CREATEINDEX职工姓名索引ON职工(职工姓名);CREATEINDEX借书证编号索引ON罚款交费单(借书证编号);CREATEINDEX经手职工编号索引ON图书入库单(经手人编号);CREATEINDEX图书入库单编号索引ON图书入库单明细(入库单编号);CREATEINDEX图书编号索引ON图书入库单明细(图书编号);CREATEINDEX经手职工编号索引ON图书报损单(经手人编号);CREATEINDEX图书报损单编号索引ON图书报损单明细(报损单编号);CREATEINDEX图书编号索引ON图书报损单明细(图书编号);CREATEINDEX借书证编号索引ON借阅(借书证编号);CREATEINDEX图书编号索引ON借阅(图书编号);
每个存储过程的功能说明和建立语句
存储过程
EXECP1100
每个触发器的功能说明和建立语句
1.编写图书入库单明细表的DELETE触发器,如已经入库(对应入库单的<是否已入库>为1),报错’已入库不能删除!’,回滚事务
(在触发器中执行ROLLBACKTRANSACTION,回滚(撤销)引起触发器DELETE的语句)
GOCREATETRIGGERtrig_delete_tsrkdmxON图书入库单明细FORDELETEASDECLARE@是否入库INT,@入库单编号INTSET@入库单编号=(SELECTTOP1入库单编号FROMdeleted)SET@是否入库=(SELECT是否入库FROM图书入库单WHERE入库单编号=@入库单编号)IF@是否入库=1BEGINRAISERROR('已入库不能删除!',16,1)ROLLBACKTRANSACTIONENDGO测试:
删除入库明细单中入库单号为100的行
触发器报错,删除失败,截图
2编写图书入库单明细表的UPDATE触发器,如已经入库(对应入库单<是否已入库>为1),报错’已入库不能修改’,回滚事务
GOCREATETRIGGERtrig_update_tsrkdmxON图书入库单明细FORUPDATEASDECLARE@是否入库INT,@入库单编号INTSET@入库单编号=(SELECTTOP1入库单编号FROMdeleted)SET@是否入库=(SELECT是否入库FROM图书入库单WHERE入库单编号=@入库单编号)IF@是否入库=1BEGINRAISERROR('已入库不能修改!',16,1)ROLLBACKTRANSACTIONENDGO
测试:
UPDATE入库明细单中入库单号为100的行
触发器报错,update失败
update图书入库单明细set数量=110where入库单编号=100
3读者借书时,要插入借阅行
编写触发器,当插入借阅时
如读者已借够可借册数,
不准借了(报错,回滚事务)
如或读者有未交罚款>100
否则
{
将读者已借册数加1,图书借阅次数加1,将图书的借出次数加1,现存量减1
}
GOCREATETRIGGERtrig_insert_jieyueON借阅FORINSERTASDECLARE@借书证编号INT,@已借册数INT,@可借册数INT,@读者类型编号CHAR(10),@未交罚款金额NUMERIC(8,2),@图书编号VARCHAR(20)SET@借书证编号=(SELECTTOP1借书证编号FROMinserted)SET@图书编号=(SELECTTOP1图书编号FROMinserted)SET@已借册数=(SELECT已借册数FROM读者WHERE证书编号=@借书证编号)SET@读者类型编号=(SELECT读者类型编号FROM读者WHERE证书编号=@借书证编号)SET@未交罚款金额=(SELECT未交罚款金额FROM读者WHERE证书编号=@借书证编号)SET@可借册数=(SELECT可借阅册数FROM读者类型WHERE读者类型编号=@读者类型编号)IF@已借册数>@可借册数BEGINRAISERROR('读者已借够可借册数!',16,1)ROLLBACKTRANSACTIONENDELSEIF@未交罚款金额>100BEGINRAISERROR('读者有未交罚款!',16,1)ROLLBACKTRANSACTIONENDELSEBEGINUPDATE读者SET图书借阅次数=图书借阅次数+1WHERE证书编号=@借书证编号UPDATE图书SET借出次数=借出次数+1,现存量=现存量-1WHERE图书编号=@图书编号ENDGO测试:
自行设计测试数据
INSERTINTO读者类型(读者类型编号,读者类型名,可借阅册数,借期天数,可续借天数)VALUES('10000','本科生',30,90,10);INSERTINTO读者(证书编号,姓名,读者类型编号,性别,出生日期,身份证编号,图书借阅次数,是否挂失,已借册数,未交罚款金额)VALUES(10,'王陆','10000','男','1999-5-6','370683199703786815',10,0,20,110);INSERTINTO借阅(借书证编号,图书编号,借书日期,还书日期,是否续借,罚款金额)VALUES(10,'101','2019-6-21',NULL,0,0);
4读者还书时,要修改借阅表,设置还书日期。
编写触发器,当修改借阅时(一次只修改一行,不考虑修改多行的情况,不用游标)
如果还书日期原来为空值,新值不是空值(这表明是还书操作)
将读者的已借册数减1,将图书的现存量加1
如果罚款金额原来为空值,新值不是空值(这表明是有罚款)
将读者的未交罚款增加
如果罚款金额原来不是空值,新值不是空值(这表明是罚款修改了)
将读者的未交罚款调整(减旧罚款,加新罚款)
GOCREATETRIGGERtrig_update_jieyueON借阅FORUPDATEASDECLARE@原还书日期DATETIME,@新还书日期DATETIME,@原罚款金额NUMERIC(8,2),@新罚款金额NUMERIC(8,2),@借书证编号INT,@已借册数INT,@图书编号VARCHAR(20)SET@原还书日期=(SELECTTOP1还书日期FROMdeleted)SET@新还书日期=(SELECTTOP1还书日期FROMinserted)SET@原罚款金额=(SELECTTOP1罚款金额FROMdeleted)SET@新罚款金额=(SELECTTOP1罚款金额FROMinserted)SET@借书证编号=(SELECTTOP1借书证编号FROMdeleted)SET@图书编号=(SELECTTOP1图书编号FROMdeleted)SET@已借册数=(SELECT已借册数FROM读者WHERE证书编号=@借书证编号)IF@原还书日期ISNULLAND@新还书日期ISNOTNULL--还书操作BEGINUPDATE读者SET图书借阅次数=图书借阅次数-1WHERE证书编号=@借书证编号UPDATE图书SET现存量=现存量+1WHERE图书编号=@图书编号ENDIF@原罚款金额ISNULLAND@新罚款金额ISNOTNULL--未交罚款增加BEGINUPDATE读者SET未交罚款金额=@新罚款金额WHERE证书编号=@借书证编号ENDIF@原罚款金额ISNOTNULLAND@新罚款金额ISNOTNULL--未交罚款修改BEGINUPDATE读者SET未交罚款金额=未交罚款金额+@新罚款金额WHERE证书编号=@借书证编号ENDGO测试:
INSERTINTO读者类型(读者类型编号,读者类型名,可借阅册数,借期天数,可续借天数)VALUES('10000','本科生',30,90,10);INSERTINTO读者(证书编号,姓名,读者类型编号,性别,出生日期,身份证编号,图书借阅次数,是否挂失,已借册数,未交罚款金额)VALUES(10,'王陆','10000','男','1999-5-6','370683199703786815',10,0,20,30);INSERTINTO借阅(借书证编号,图书编号,借书日期,还书日期,是否续借,罚款金额)VALUES(10,'101','2019-6-21',NULL,0,0);SELECT*FROM借阅UPDATE借阅SET还书日期='2019-6-21'WHERE借书证编号=10UPDATE借阅SET罚款金额=罚款金额+5WHERE借书证编号=10SELECT*FROM借阅SELECT*FROM读者SELECT*FROM图书
5读者交罚款时,要插入罚款交费单
编写触发器,当插入罚款交费单
将读者的未交罚款减少
GOCREATETRIGGERtrig_insert_fakuanON罚款交费单FORINSERTASDECLARE@借书证编号INT,@金额NUMERIC(8,2)SET@借书证编号=(SELECTTOP1借书证编号FROMinserted)SET@金额=(SELECTTOP1金额FROMinserted)IF@金额ISNOTNULLBEGINUPDATE读者SET未交罚款金额=未交罚款金额-@金额WHERE证书编号=@借书证编号ENDGO测试:
INSERTINTO读者类型(读者类型编号,读者类型名,可借阅册数,借期天数,可续借天数)VALUES('10000','本科生',30,90,10);INSERTINTO读者(证书编号,姓名,读者类型编号,性别,出生日期,身份证编号,图书借阅次数,是否挂失,已借册数,未交罚款金额)VALUES(10,'王陆','10000','男','1999-5-6','370683199703786815',10,0,20,100);INSERTINTO借阅(借书证编号,图书编号,借书日期,还书日期,是否续借,罚款金额)VALUES(10,'101','2019-6-21',NULL,0,0);INSERTINTO罚款交费单(交费单号,日期,职工编号,金额,借书证编号)VALUES(1,'2019-6-22',10001,100,10);select*from读者
6编写触发器,借书表不允许DELETE操作
GOCREATETRIGGERtrig_delete_jieyueON借阅FORDELETEASRAISERROR('借书表不允许DELETE操作',16,1)ROLLBACKTRANSACTIONGO测试:
DELETEFROM借阅
7编写报损单触发器
1完成设计报告《6.1完整的测试数据》
查询图书表,看看结果是否正确,截图到设计报告.(注意报损的图书册数未计入,应如何解决)
查询读者表,看看结果是否正确,截图到设计报告.
2完成设计报告《6.2测试查询语句》。
写出下列SQL语句并运行通过
例如:写出用LIKE的查询要求,并写出查询语句.
查询要求:
查询书名中含有’数据库’的图书编号,书名
查询语句:
(1)写出用到2表连接的查询要求,并写出查询语句.
SELECT出版社.出版社编号,出版社名称,出版社地址FROM出版社,图书WHERE图书.出版社编号=出版社.出版社编号
(2)写出用到3表连接的查询要求,并写出查询语句.
SELECT*FROM读者,图书,借阅WHERE图书.图书编号=借阅.图书编号AND读者.证书编号=借阅.借书证编号
(3)写出用到GROUPBY的查询要求,并写出查询语句.
SELECT图书.图书类型编号,书名FROM图书,图书类型WHERE图书.图书类型编号=图书类型.图书类型编号GROUPBY图书.图书类型编号,书名
(4)写出用到IN子查询的查询要求,并写出查询语句.
查询出版社地址在北京的图书
SELECT书名FROM图书WHERE出版社编号IN(SELECT出版社编号FROM出版社WHERE出版社地址='北京')
(5)写出用到NOTIN子查询的查询要求,并写出查询语句.
查询出版社地址不在北京的图书
SELECT书名FROM图书WHERE出版社编号NOTIN(SELECT出版社编号FROM出版社WHERE出版社地址='北京')
(6)写出用到EXISTS子查询的查询要求,并写出查询语句.
SELECT书名FROM图书WHEREEXISTS(SELECT*FROM出版社WHERE图书.出版社编号=出版社.出版社编号AND出版社地址='北京')
(7)写出用到NOTEXISTS子查询的查询要求,并写出查询语句.
SELECT书名FROM图书WHERENOTEXISTS(SELECT*FROM出版社WHERE图书.出版社编号=出版社.出版社编号AND出版社地址='北京')
(8)对每个视图,写出查询语句
1.入库单视图
2.报损单视图
3.读者未还借书视图
4.图书分类库存视图
4.借出次数前100图书视图
数据库的概念设计,对E-R图的设计和简化;数据库的逻辑结构设计,建立起表结构;建立索引,索引表结构的设计;SQL建表,建立存储过程,建立触发器,数据插入后的测试。
在数据库概念设计中对各个实体性的确立和划分,这要从图书管理使用的实际出发,确定实体型和各个实体之间关系。
在E-R图向关系模式转换的过程中要明确好主码、外码等属性,建立好各个表之间的逻辑结构。
该图书借阅管理系统还存在着许多问题,在逻辑结构设计的过程中一些表虽然减少了冗余,但在查询使用的过程中却存在着语句复杂,使用复杂的问题。同时用于实时检验和修改的触发器设计过于简陋,触发器数量太少,使得该系统不太成熟。
通过对图书借阅管理系统的设计,一方面让我明白了数据库原理在图书管理上运用的流程,另一方面也让我初步了解了SQL-server2017的开发工具的使用方法,熟悉了SQL建立数据库的一系列过程。在课程设计的过程中也遇到了一些问题,但是通过请教老师和同学讨论,解决了不少问题,对数据库系统原理也用了一个体系化的理解,收获很大。
数据库的使用和高级程序开发的关系密不可分,学好数据库系统原理对于进一步理解程序设计流程和软件开发应用有着很大作用,通过本学期数据库系统原理的学习,虽然现在还没有真正使用数据库和高级语言一起用于程序的开发,但对开发流程和其中用到的数据库原理已经有所理解了。