ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

图书管理系统数据库设计:E-R图、数据流与关系模式落地指南

图书管理系统数据库设计:E-R图、数据流与关系模式落地指南 简介这份PDF是一份图书管理系统的数据库设计文档适合计算机相关专业学生、毕业设计开发者以及备考数据库课程的读者参考。内容围绕系统核心设计展开涵盖E-R图、数据流图、关系模式及数据库字段定义四大部分E-R图清晰刻画管理员、读者、书籍、书架、阅览室等实体及其联系数据流图梳理办证、借书、还书、缴纳欠费等业务流程关系模式给出各实体对应的主外键及表间关联字段定义表则逐一说明表结构、数据类型、取值范围与约束可直接用于建表与后续开发。资源包仅含1个PDF文件约332KB内容紧凑、便于随时翻阅。目前已有2718人学习下载适合需要快速理解图书管理系统数据建模思路、完成课程设计或论文相关图表绘制的用户。1. 图书管理系统E-R图、数据流与关系模式为什么先画图再建表能省一半返工带过不少做图书管理系统的人最普遍的操作是打开数据库工具直接建表。表名叫 book字段是 id、name、author、number看着挺完整。等做到借书功能一本书被借走之后库存字段没有联动扣减同一本书再次录入时主键冲突还书时想查“这本书之前被谁借过”发现历史记录被覆盖掉了。项目到中期返工表结构再回头补 E-R 图和数据流图这种情况我见过太多次。图书管理系统的 E-R 图、数据流和关系模式不是课程设计交差用的几张图而是把“借书、还书、查询、库存”这些动作翻译成表结构和数据流向的唯一可靠路径。这篇笔记就照着图书管理系统这个最常见需求把三件套怎么画、怎么转成关系模式、落地时有哪些坑完整讲一遍新人和有两年经验的开发都能直接照着做。2. 从借还书需求到E-R图实体、属性、联系的识别方法与三个取舍2.1 先从需求里圈出实体读者、图书、管理员和出版社哪个都不能少实体识别是第一步也是最容易漏的一步。图书管理系统最常见的需求描述是读者可以查询图书、借书、还书管理员可以录入图书、维护读者、查看借阅记录系统要能统计库存和借出数量。拆到这里实体大致有读者、图书、管理员。但做过数据库设计的人一眼能看出还缺两个出版社和图书分类。理由很简单。一本书的出版社信息如果直接塞在图书表里同一个出版社出版几百本书出版社名称和地址就会在几百行里重复出现出版社改一次地址图书表要跟着改几百行。图书分类同理分类名称变更时不想连累图书表就得把分类单独拎出来。这两个实体漏掉后面关系模式必然出现冗余和更新异常。实体圈定之后逐个列属性。读者实体读者号、姓名、性别、证件类型、证件号、办证日期、读者状态、可借数量。图书实体馆藏条码、书名、ISBN、作者、价格、入库日期、状态。管理员管理员号、姓名、账号、密码、权限级别。出版社出版社ID、名称、地址、联系电话。图书分类分类ID、分类名称、父分类ID。这里有个实际经验属性一定要从需求描述里逐字抠。需求里写了“需要记录读者联系方式用于逾期通知”就加 phone没写就坚决不加。属性列表越界是 E-R 图画得臃肿的最常见原因后面转关系模式时一半字段没意义应用层写插入语句还得多传一堆空值。2.2 真正容易画错的是联系借阅是多对多但库存变动是一对多联系是 E-R 图的核心。图书管理系统里读者和图书之间的“借阅”联系怎么看都像多对多一个读者可以借多本书一本书在不同时间可以被多个读者借。但要注意E-R 图里画联系看的是在一次业务发生时两个实体的实例如何配对而不是历史累计。一次借阅动作是一个读者对应一个馆藏副本所以“借阅”标成 M:N 是合理的而且这个多对多联系还自带属性借出日期、应还日期、归还日期。这里最容易出现两个设计决策。第一有属性的多对多联系在关系模式里必须转成一张独立的借阅记录表不能简单地在读者表加外键或在图书表加外键。第二管理员和图书之间是“管理维护”联系1:N管理员和读者之间是“审核维护”联系1:N图书和出版社是 N:1图书和图书分类是 N:1。把这些连线画全E-R 图才完整。很多教材范例只画读者、图书、管理员三个实体漏出版社和分类后面转关系模式时只能把出版社字段硬塞进图书表这是第 5 章要讲的坑而且是最常见的一个。E-R 图的符号用法也值得说一句实体用矩形联系用菱形属性用椭圆主键属性在椭圆下面加下划线。画图工具用 draw.io、Visio 或者 ProcessOn 都行甚至手画拍照也行关键是符号统一。画完检查三件事每个实体都有主键每个联系两端都标了度数每个属性只归属于一个实体。这三件事做完E-R 图部分可以收工。2.3 属性设计的三次取舍候选键、派生属性与弱实体属性设计有三个执行时总出问题的点。第一候选键选择。读者实体有两个候选键读者号和证件号。读者号是系统内分配的生成规则简单读者换身份证也不会变适合做主键。图书实体的候选键更微妙ISBN 是书目级别的标识不是馆藏副本级别的。同样一本《数据结构》图书馆采购了 5 册5 册的 ISBN 相同但条形码馆藏条码完全不同。图书实体的主键应当用馆藏条码ISBN 只作为书目属性。到关系模式里图书表和书目表是两张表这是图书管理系统设计里最重要的一次主键决策。第二派生属性。图书实体的“当前可借数量”“在馆数量”读者实体的“已借数量”都属于派生属性可以由借阅记录、读者状态等基础数据实时算出来。E-R 图里可以不画也可以画但标注“派生不存储”。实际开发中这两个数量如果做成存储字段靠程序在每次借书、还书时同步更新总有一次会因为异常分支例如事务回滚、直接改库、定时任务漏执行导致库存数字和借阅记录对不上。最终还是要靠实时计算或定时任务重算兜底。第三弱实体。“图书副本”相对于“书目”是弱实体书目离开图书管理系统依然有意义但“图书副本”离开“书目”就完全失去语义副本的条码号只在一本书的范围内唯一。E-R 图里弱实体用双线矩形表示它与书目之间用双线菱形联系。这一层如果不画清楚建表时会把条码、ISBN、书名、作者全塞进一张表然后发现 ISBN 相同的书无法表达多副本。这个细节决定了图书管理系统能不能支持“馆藏多册”这个刚需。提示实体确定后先在纸上列一遍属性清单自上而下检查有没有哪个属性在多个实体里重复出现。重复出现的就是需要单独建实体的信号不是冗余设计的理由。3. 数据流图从顶层拆到1层借书流程如何变成可查的数据字典3.1 顶层DFD确定边界读者和管理员是两个外部实体系统是圆心数据流图回答的问题是数据从哪里来、经过哪些处理、存到哪里去。画法是从顶层到 0 层再到 1 层逐层分解不能用一张图画到底。顶层 DFD 只画一个圆代表整个图书管理系统外部实体画两侧读者和管理员。数据流怎么标读者发起的查询请求、借书请求、还书请求流入系统系统返回的查询结果、借阅凭证、逾期提示从系统流出。管理员发起的图书录入、读者信息维护、库存盘点请求流入系统系统的库存报表、借阅清单流出。顶层 DFD 就一张圆加四个外部实体连线目的是让所有人确认系统边界哪些功能做进系统哪些是线下手工处理。例如“图书采购审批”如果没有进入需求范围就不要在顶层 DFD 里出现否则后面讨论时永远说不清职责。顶层图的另一个作用是界定外部实体的数量。图书管理系统通常只有读者和管理员两个外部实体。如果还有人把“出版社”也画成外部实体说明他在设想“出版社直接把新书信息推送给系统”的功能这个需求没有明确前不要自作主张。3.2 0层DFD分五个加工借书、还书、查询、统计和读者管理0 层 DFD 把顶层那个圆拆成若干个加工处理过程。图书管理系统的常见拆分是五个加工借书处理、还书处理、图书查询、读者管理、库存统计。每个加工要求有编号例如 1-借书处理、2-还书处理、3-图书查询、4-读者管理、5-库存统计。编号的意义在于下钻1 号加工继续细化成 1.1、1.2、1.3形成 1 层 DFD这样整棵树从顶层到最底层可追溯。0 层图还需要画数据存储DFD 里用开口矩形表示。图书管理系统需要哪些存储读者表、图书表馆藏、借阅记录、处罚记录、管理员表、出版社表。这里有一个高频错误数据流直接画成“外部实体 → 存储”跳过了加工。比如读者查询图书数据流不能从读者直接画到图书表必须从读者出发进入“图书查询”加工加工再读图书表返回结果。数据流图里外部实体不直接操作存储这是规则也是后面检查图是否规范的第一步。3.3 用借书流程做1层DFD验证、登记、改状态三个步骤必须分离1 层 DFD 通常挑最复杂的加工来画图书管理系统里最复杂的是借书处理。把 1 号加工“借书处理”往下拆常见做法是三个子加工1.1 验证读者1.2 登记借阅记录1.3 更新图书状态。画法如下1.1 输入读者号和馆藏条码检查读者状态是否正常、当前借阅数量是否达到上限输出“验证通过”或“拒绝原因”数据流。验证通过后1.2 接收“读者号、馆藏条码、借出日期、应还日期”数据流写入借阅记录存储并输出一张借阅凭证给读者。1.3 再根据 1.2 写入成功的信号把馆藏副本状态从“在馆”改为“借出”。这三个子加工的顺序依赖在 DFD 里就是数据流的先后关系。这张 1 层图最大的价值在于每一个子加工对应了后面关系模式里的一次 SQL 操作。1.1 对应 SELECT 读者表并按条件 COUNT 借阅记录1.2 对应 INSERT 借阅记录1.3 对应 UPDATE 馆藏表。这样图与代码的映射关系直接可用也是数据流图区别于其他文档的核心价值。接着补数据字典。我不主张把数据字典写成几百行的大词典那样没人维护。只需要把关键数据流定义清楚借书请求流、还书请求流、查询请求流、逾期信息流。每条数据流列出组成数据项例如借书请求流 读者号 馆藏条码 借出时间。把这些数据项与 E-R 图的属性表逐项对齐就能保证图与图之间自洽而不是各画各的。数据字典里每个数据项的类型和长度以第 4 章的关系模式为准两边不一致时多数是关系模式漏字段而不是数据流图画错。4. 把E-R图转成关系模式四张核心表的字段设计与第三范式检查4.1 E-R图转关系模式的四条规则与图书管理系统的映射E-R 图到关系模式的转换规则是固定的四条。第一每个实体转成一张表实体属性转为表字段主键属性转为表主键。第二多对多联系转成独立的关系表联系上自带的属性一并放入。第三一对多联系不单独建表在“多”端实体表中加外键指向“一”端主键。第四一对一联系视情况合并通常合并到使用频率高的一侧。套到图书管理系统读者、管理员、出版社、图书分类各转成一张实体表。读者与图书的 M:N 借阅联系转成借阅记录表借出日期、应还日期、归还日期这些联系属性放进这张表。图书与出版社是 N:1图书表加出版社 ID 外键。图书与图书分类是 N:1图书表加分类 ID 外键。管理员只参与“维护”这类 1:N 联系不产生新关系表通过管理员号在读者表和图书表里做外键记录操作人即可。一个细节值得强调如果 E-R 图里已经画了“图书副本”弱实体那么副本转成馆藏表条码号为主键书目 ID 为外键。如果 E-R 图里没做拆分直接按“图书”实体转表ISBN 和条码就会挤在同一张表多副本的书只能存一行。这一步是整份设计文档质量的分水岭后面 5.2 节会专门写这个翻车案例。4.2 建表之前必须定清的字段参数核心三张表的类型、长度与默认值关系模式图或表结构文档里最怕写“字符串”“日期”这种模糊定义。图书管理系统的核心三张表字段参数一次定清建表时就不会犹豫。读者表字段名类型长度约束与默认值说明reader_idINT11主键自增读者号系统内部生成reader_nameVARCHAR50非空读者姓名id_cardVARCHAR18非空唯一证件号一个读者一条phoneVARCHAR11可空联系电话逾期通知用reg_dateDATE-默认当前日期办证日期statusTINYINT4默认 11正常 2挂失 3注销max_borrowTINYINT4默认 5最大可借数量馆藏表字段名类型长度约束与默认值说明barcodeVARCHAR20主键条形码每册一个book_idINT11外键指向书目表书目 IDlocationVARCHAR50可空架位信息in_dateDATE-默认当前日期入库日期stateTINYINT4默认 11在馆 2借出 3维修 4下架借阅记录表字段名类型长度约束与默认值说明borrow_idBIGINT20主键自增借阅流水号reader_idINT11外键指向读者表读者号barcodeVARCHAR20外键指向馆藏表馆藏条码borrow_dateDATETIME-默认当前时间借出时间due_dateDATE-非空应还日期由借期规则计算return_dateDATE-可空归还日期空值表示未还这四个参数经常被改坏。barcode 用 VARCHAR 而不用 INT因为条形码可以以 0 开头也可能含字母。due_date 用 DATE 不用 DATETIME逾期判断按天不按秒精确到时分会带来跨天判断的额外逻辑。return_date 允许 NULLNULL 表示未还这是天然业务语义不需要额外状态位。borrow_id 用 BIGINT图书管理系统跑三五年后借阅记录远比想象多INT 上限很容易被突破初期定 BIGINT 不需要额外成本。4.3 第三范式检查图书分类和出版社为什么要单独建表关系模式画完做一遍范式检查。图书管理系统达到第三范式即可不用追求更高。拿书目信息举例如果书目表里直接放“分类名称”“出版社名称”表面看起来查询省了一次 JOIN实际上存在传递依赖——book_id 决定了分类 ID分类 ID 又决定了分类名称。一旦分类改名必须同步改所有相关图书行漏改一行就数据不一致。解决办法就是 4.1 节里的规则分类和出版社各自成表书目表只保留外键 ID查询时用 JOIN 取名称。借阅记录表是另一个重灾区。设计者图省事把读者姓名、书名连带放进借阅记录表。范式上直接违规不用多说实际业务上还有一个严重问题读者改名后历史借阅记录的姓名要不要跟着改如果跟着改记录失去历史语义如果不跟着改表里出现矛盾数据。借阅记录里只保留 reader_id 和 barcode查询时 JOIN 读者表、书目表取姓名和书名这才是图书管理系统的正确做法。注意范式检查不是越高级越好。图书管理系统到 3NF 足够。刻意把字段拆到第五范式级别比如把读者姓名拆成姓氏和名字两列只会让写 SQL 的人怀疑人生没有任何实际收益。5. 图书管理系统数据库设计的避坑清单五个从E-R图阶段就能避免的翻车点5.1 用“读者号图书条码”做借阅表主键同一本书续借直接翻车现象借阅记录表主键设计成 reader_id barcode 联合主键看起来能唯一标识一条借阅。等实现“续借”功能时先更新原记录再插入新记录插入直接报主键冲突或者被迫原地更新应还日期结果续借前的借阅历史轨迹丢失。更隐蔽的是“同一读者借同一本书的不同副本”因为 barcode 不同联合主键不会冲突设计者还以为没问题直到续借场景一测就露馅。原因联合主键表达的是“一个读者、一本书、一次借阅唯一”但借阅记录本质是流水账事件。一次借阅结束下一次借阅是全新事件不应该被旧主键锁死。任何表达“发生过的事件”的表都不该用业务字段拼联合主键。解决用自增 BIGINT 作为借阅流水 ID 做主键reader_id 和 barcode 只加普通索引用于查询。续借就是 UPDATE due_date不存在主键冲突问题。这条血泪经验我用了好几次才长记性只要表表达的是事件而不是实体一律上代理主键。5.2 把ISBN当物理图书主键十本同名书只剩一行记录现象图书表主键设计成 ISBN规则上看着合理——ISBN 全球唯一。入库十本《深入理解计算机系统》十本同一个 ISBN只插进去一条记录。后续每一本都覆盖前一本馆藏副本数永远是 1读者借走一本其他九本就凭空消失了。原因把“书目”和“馆藏”两个概念混淆了。ISBN 标识的是书目不是物理上存在的那本可借的书。图书馆采购十本同一本书就是十个物理副本需要十个条码号。解决书目表和馆藏表拆分。书目表存 book_id、ISBN、书名、作者、出版社 ID、分类 ID馆藏表存 barcode、book_id 外键、入库日期、架位、状态。“当前在馆几本”用 COUNT 馆藏表 WHERE state1 实时算而不是在书目表里维护一个库存字段。这个设计在 E-R 图阶段就决定了书目是独立实体馆藏是弱实体。图漏了弱实体表必然翻车。5.3 数据流图与E-R图字段对不上借书请求里的读者状态在关系模式里没有现象1 层 DFD 里 1.1 验证读者数据字典里记录了“读者状态正常”这个数据项转到关系模式时读者表忘记设计 status 字段或者数据字典里“超出可借数量”的判断没有对应任何可以统计的字段。代码写一半发现查询条件没有字段可用临时往表里加列。原因数据流图是行为视角E-R 图是结构视角两边各画各的没有做字段对齐。DFD 中出现的每一个临时数据项要么来自某张表的字段要么是这些字段的计算结果不可能凭空产生。解决关系模式定稿后拿数据字典里的复合数据流逐项过一遍把每项在表字段里的来源标出来。标不出来的就是漏字段或者派生属性没有定义计算规则。我现在的习惯是做一张字段映射表一个数据项一行源表字段写不全不动建表语句。这个动作多做一次后面写 SQL 时能少改一半。5.4 还书加工里没有超期分支罚金数据流永远为空现象DFD 里还书处理只画了一条被动流程登记归还日期、更新图书状态。系统上线后读者逾期还书罚金算不出来只能人工催缴或干脆不罚。运营问起来开发只能说“需求里没提”。原因需求里的“逾期罚金”在分析阶段就没有进入数据流图。还书加工的 1 层 DFD 里缺少对“应还日期 vs 当前日期”的条件判断和分支数据流。DFD 漏了分支关系模式自然也不会设计处罚记录表整个功能从源头缺失。解决在还书 1 层 DFD 里加判断分支取借阅记录里的 due_date与当前日期比较超期则生成罚金数据流向处罚记录存储同时输出给读者一张催缴/扣款通知未超期只登记归还日期。关系模式这边处罚记录表要对应存在罚金 ID、借阅记录 ID、金额、缴纳状态。这是典型的“行为模型倒逼结构模型补实体”的案例画 DFD 时把分支画全建表时才知道还缺一张表。5.5 外键字段类型不一致关联查询返回空还是报错全靠运气现象读者表 reader_id 是 INT(11)借阅表里外键字段手滑写成 VARCHAR(11)。建表时 MySQL 根本不报错表照样建得出来。查询时 MySQL 做隐式类型转换后接的字符串拼进 SQL 时该走索引的查询不走索引结果时对时不对看起来跟玄学一样。原因设计关系模式时没有统一检查外键字段与参照主键的类型和长度。复制字段定义时手滑或者跨表凭记忆敲没有核对这一步。问题是 MySQL 对 INT 和 VARCHAR 的比较容忍度太高不报错只在性能和数据一致性上慢慢体现。解决关系模式文档里对每一个外键字段直接标注参照来源例如“fk_borrow_reader → 参照 reader(reader_id)”建表后用一条 SQL 从 information_schema 里把所有外键的参照关系捞出来与文档核对表逐行比对。-- 从元数据里查出所有外键约束及参照关系核对类型是否与文档一致 SELECT TABLE_NAME, COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME FROM information_schema.KEY_COLUMN_USAGE WHERE REFERENCED_TABLE_NAME IS NOT NULL AND TABLE_SCHEMA library_db;这条 SQL 跑出来的结果和关系模式文档里的外键对照表逐行比对能避免一大半关联查询翻车。我之前接过一个 php 写的图书管理系统问题全出在这里表结构看着都对一 JOIN 就慢最后就是用这条 SQL 查出三处类型不一致。6. 用SQL把关系模式落地建表语句与借阅联查的可执行验证关系模式的最终宿命是数据库里的真实表。我习惯在建表后跑两个验证查询确认关系模式与第 3 章数据流图的自洽性。先看核心表落地-- 读者表主键自增status 1正常 2挂失 3注销 CREATE TABLE reader ( reader_id INT NOT NULL AUTO_INCREMENT, reader_name VARCHAR(50) NOT NULL, phone VARCHAR(11) NULL, reg_date DATE NOT NULL DEFAULT (CURRENT_DATE), status TINYINT NOT NULL DEFAULT 1, PRIMARY KEY (reader_id) ); -- 馆藏表barcode 标识每一册物理书book_id 指向书目 CREATE TABLE collection ( barcode VARCHAR(20) NOT NULL, book_id INT NOT NULL, state TINYINT NOT NULL DEFAULT 1, PRIMARY KEY (barcode), CONSTRAINT fk_collection_book FOREIGN KEY (book_id) REFERENCES book(book_id) ); -- 借阅记录表代理主键 borrow_idreader_id 和 barcode 只做外键 CREATE TABLE borrow_log ( borrow_id BIGINT NOT NULL AUTO_INCREMENT, reader_id INT NOT NULL, barcode VARCHAR(20) NOT NULL, borrow_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, due_date DATE NOT NULL, return_date DATE NULL, PRIMARY KEY (borrow_id), CONSTRAINT fk_borrow_reader FOREIGN KEY (reader_id) REFERENCES reader(reader_id), CONSTRAINT fk_borrow_collection FOREIGN KEY (barcode) REFERENCES collection(barcode) );参数上注意两点phone 用 VARCHAR(11) 是兼容前导 0 和后续可能出现的座机号DEFAULT (CURRENT_DATE) 是 MySQL 8.0 起的合法表达式默认值写法5.7 及以下版本要用 DEFAULT CURRENT_DATE 或在应用层赋值。建表后的第一个验证查询对应第 3 章数据流图里“当前在借”的数据流列出所有未还的借阅记录关联读者姓名和书名。这个查询跑得通、结果与 DFD 一致说明外键设计和 JOIN 关系正确。-- 验证当前在借列表借阅、读者、馆藏、书目四张表关联 SELECT b.borrow_id, r.reader_name, bk.book_name, c.barcode, b.borrow_date, b.due_date FROM borrow_log b JOIN reader r ON b.reader_id r.reader_id JOIN collection c ON b.barcode c.barcode JOIN book bk ON c.book_id bk.book_id WHERE b.return_date IS NULL;第二个验证是库存统计按书目聚合列出总册数、在馆数、借出数。这个查询对应 0 层 DFD 里的“库存统计”加工。能跑出三个正确数字说明状态字段设计和借阅记录的未还状态逻辑都没有问题。-- 验证库存统计馆藏总数、在馆数量、借出数量按书目分组 SELECT c.book_id, COUNT(*) AS total_copies, SUM(CASE WHEN c.state 1 THEN 1 ELSE 0 END) AS available_copies, SUM(CASE WHEN c.state 2 THEN 1 ELSE 0 END) AS borrowed_copies FROM collection c GROUP BY c.book_id;这两个查询通过关系模式设计就算闭环了。这么多年做下来我的习惯是建表之前把关系模式打印出来对着 E-R 图和数据流图逐张翻不确认清楚不动建表语句。看起来多花一个小时实际省下一周数据库返工的弯路。图书管理系统这种经典业务E-R 图、数据流、关系模式三件套一次做对后面开发阶段你几乎不会再碰表结构。希望帮到你。本文还有配套的精品资源点击获取
返回列表