从ER图到关系模型:数据库设计核心概念与实践指南
发布时间:2026/9/11 5:59:01 锦皓数字建站

1. 实训项目为什么必须从ER图开始先建模还是先建表带过几轮项目实训之后我发现一个几乎每年都会出现的共性现象小组拿到需求文档后端同学第一反应就是打开Navicat开始建表建到第三四张表的时候开始卡壳——读者和图书到底怎么关联一个人借多本书一本书被多个人借过这外键加在哪边然后一群人围在屏幕前争论半天最后发现需求根本没理清表结构推倒重来。所以我现在带实训项目第一周反复强调的就是一句话先别急着写代码更别急着建表把ER图分析透了再动手。这句话不是老生常谈而是无数个项目翻车换来的教训。数据库表结构是一个系统的地基地基画歪了后面所有功能开发都会跟着错位。你后端的Mapper要改、前端的接口要调、测试用例要重写返工成本远比想象中大。这里需要先明确三个层次的数据模型很多教材讲过但实际做项目时大家容易混淆概念模型与具体数据库无关描述业务世界里有哪几类对象、对象之间什么关系。这一层用ER图表达是需求分析阶段的主要产出。逻辑模型把概念模型转换成接近表结构的形式确定主键、外键考虑范式约束。也就是平时说的关系模型。物理模型落到具体数据库里确定字段类型、索引、存储引擎最终生成建表SQL。ER图属于第一层却直接影响第二层和第三层。实训项目里需求不会像真实企业那样有专门分析师来梳理所以这一层更需要团队自己补上。什么时候画ER图最合适我的建议是需求文档大致梳理完毕、功能清单列出来之后用一到两天集中把ER图做出来再进入表结构设计。我见过不少同学觉得画ER图是走形式直接打开MySQL Workbench反向后端表结构生成一张表关系图就当作ER图交差。这是典型的把物理模型当概念模型用。ER图的价值在于逼着你去思考业务规则读者能不能同时借十本书一本书的副本怎么管理超期罚款和借阅记录是什么关系这些在表结构一旦定下来之后再改代价完全不同。2. 实体、属性、联系ER图三大核心要素怎么判断ER图看上去简单无非是矩形、椭圆、菱形但真正画起来很多团队会在三个基础问题上反复扯皮这个东西到底算实体还是属性这个联系是几对几属性该放这个实体还是那个实体这些问题本质上是业务理解问题不是画图技术问题。2.1 实体判断标准这个对象能不能被独立描述实体Entity是现实世界中可区别于其他对象的事物。判断一个概念是否为实体我常用的标准就一条它有没有独立的特征需要被记录并且能不能被唯一区分。以图书借阅系统为例。读者是实体因为读者有编号、姓名、手机号等一堆属性需要存而且每个读者都有唯一编号。图书是实体同理。但借书这个动作是不是实体不是它描述的是读者和图书之间的行为应该用联系来表达。不过借阅记录是实体——因为每次借书行为产生了一条可独立描述的数据它有借书日期、应还日期、归还状态这些自己的属性。我经常用一个例子帮大家区分地址。如果系统里只需要在读者信息里显示一个联系地址字符串那它就是读者的属性。但如果你的业务需要对地址做统计分析比如按城市统计读者分布甚至地址本身包含省、市、区、街道多个结构化字段那地址就值得独立成实体。判断的核心是它自己有没有足够多需要管理的细节。2.2 属性取舍什么时候属性该升级为实体属性Attribute是实体的特征。画ER图时最容易被问住的是出版社应该算图书的属性还是独立实体。如果图书表里只记录一个出版社名称那它是属性没有争议。但现实中出版社还有地址、联系电话、成立年份这些信息尤其图书馆采购图书时可能要按出版社维度的统计报表留着这些数据价值很大。这时候把出版社独立成实体与图书形成1:N联系逻辑上更完整后期扩展性也好。我的经验是当一个属性下面还挂着子属性或者它自身需要被多个实体共享时就应该升级为实体。例如图书分类如果只是存一个字符串计算机/文学/历史那是属性但如果分类有编码、有层级结构、有排序号再当作属性就会很别扭。这里顺便强调一下主键。画ER图时就要把主键确定下来而不是等到建表时再想。ER图的约定是主键属性的名称加下划线标注。图书编号、读者编号这种业务代码型主键适合实训项目语义清晰答辩时也容易解释自增ID也可以但要注意在ER图上说明清楚生成策略。2.3 联系基数从两端各问一次一个对应几个联系Relationship是实体之间的业务关联最关键的是判断基数Cardinality。基数有三种1对1、1对N、多对多。判断方法我教学生一个土办法站在其中一个实体的一端问一个A最多对应几个B再站到另一端问一个B最多对应几个A两个问题的答案组合起来就是基数。举个例子学生和课程一个学生能选多门课一门课能被多个学生选所以是M:N。国家和首都一个国家有且仅有一个首都一个首都只属于一个国家所以是1:1。出版社和图书一个出版社出版很多书一本书通常只属于一个出版社暂不考虑联合出版所以是1:N。还有两个常见变体需要提醒部分参与约束联系的实体是否需要全部参与。比如管理员—图书一个管理员负责维护一批图书但不是每本图书都有唯一对应管理员这种在实操中往往做成操作日志而不是直接建立外键关联。三元联系三个实体同时发生联系。图书借阅场景里读者—图书—管理员在借阅行为中缺一不可但更合理的建模是先拆借阅记录实体再分别建立与三者的一对多联系。实训项目尽量不画三元联系拆开更清晰后面转关系模型也简单。3. 图书借阅系统的ER图完整拆解从需求文档到概念模型图书借阅是图书馆的核心服务也是实训项目里出现频率最高的题目之一。下面演示一遍从需求分析到完整ER图产出的全过程这也是网上那些ER图例题最常考的类型。3.1 从需求文本里提取实体清单拿到一段需求描述第一步是把名词圈出来。这个方法虽然原始但确实好用。原始的图书借阅系统需求通常包含读者可以查询图书信息、办理借书和还书手续管理员负责维护图书信息和读者信息借阅时需要记录借书时间和应还时间读者如果超期还书会产生罚款图书有分类方便读者按类别检索。圈出名词后得到读者、图书、管理员、借阅记录、罚款、分类、出版社。接着逐一判断它们是不是实体名词是否实体理由读者是有独立属性可被唯一区分图书是有独立属性可被唯一区分管理员是需要记录账号、姓名、角色借阅记录是每次借书行为有独立数据罚款视情况如果只作为借阅记录的金额字段算属性如果涉及缴纳状态、减免记录独立实体更清晰分类是有编码、名称、层级结构时独立建模出版社是需要记录联系方式等细节时独立建模实训项目里如果时间有限罚款可以先作为借阅记录的一个属性字段不需要单独建模。分类和出版社是否独立成实体取决于需求里是否有按分类浏览、按出版社检索的功能。我一般建议把这两个都做成独立实体这样图更完整转关系模型后表结构也更规范答辩时也有材料可讲。3.2 实体属性设计先列必填项再谈扩展项实体确定之后给每个实体列属性。属性列得好不好直接影响后面建表能不能落地。我习惯分两轮列属性第一轮只列当前需求明确要求的数据项第二轮再补充作为主键、外键关联所需的关键字段。以下是一组完整度适中的属性设计实体主键其他属性读者读者编号姓名、证件类型、证件号码、手机号、邮箱、注册日期、状态图书图书编号书名、作者、ISBN、出版日期、价格、馆藏总量、可借数量管理员管理员编号姓名、登录账号、密码、联系电话、角色借阅记录借阅编号借书日期、应还日期、实际归还日期、状态出版社出版社编号出版社名称、联系电话、地址分类分类编号分类名称、父分类编号注意一个细节读者实体没有直接放借了几本书这样的字段。数量信息不应作为属性存放而应该通过关联查询计算得出。数据库设计讲第三范式就是为了避免这种冗余。但馆藏总量和可借数量留在图书上是有意为之这叫适度冗余目的是让读者在查询图书列表时不用每次都统计借阅记录这个取舍后面会细说。3.3 联系与基数判断读者、图书、借阅记录三者的真实关系实体之间有哪些联系同样回到业务规则里去逐个分析。联系参与实体基数理由借阅读者—图书M:N一个读者借多本书一本书被多个读者借过办理管理员—借阅记录1:N一个管理员办理多条借阅记录产生读者—借阅记录1:N一个读者名下有多条借阅记录对应图书—借阅记录1:N一本图书会在多条借阅记录中出现出版出版社—图书1:N一个出版社出版多本图书归属分类—图书1:N一个分类下有多本图书这里最关键在于读者和图书的M:N联系。概念模型阶段我们可以直接用菱形画出借阅联系连接读者和图书但到了第4章转关系模型时这个M:N必须拆成借阅记录这个中间实体来处理。也就是说借阅记录既是联系语义上表达了借阅行为又是实体有自己的属性。这种联系实体在ER图分析里是个核心概念理解透了这个点后面表结构设计就顺了。3.4 画出完整ER图实体、属性、主键、联系一图说清把上面的分析落到图上可以这样表示用文字描述实际画图时按同样结构读者(读者编号, 姓名, 证件类型, 证件号码, 手机号, 邮箱, 注册日期, 状态)图书(图书编号, 书名, 作者, ISBN, 出版日期, 价格, 馆藏总量, 可借数量)管理员(管理员编号, 姓名, 登录账号, 密码, 联系电话, 角色)借阅记录(借阅编号, 借书日期, 应还日期, 实际归还日期, 状态)出版社(出版社编号, 出版社名称, 联系电话, 地址)分类(分类编号, 分类名称, 父分类编号)实体间联系出版社(1) —— 出版(N) —— 图书分类(1) —— 归属(N) —— 图书读者(1) —— 产生(N) —— 借阅记录图书(1) —— 对应(N) —— 借阅记录管理员(1) —— 办理(N) —— 借阅记录这里借阅记录同时和读者、图书、管理员三个实体形成1:N联系实际上就是把原来的M:N联系借阅处理成了实体后自然得到的结果。ER图画到这个程度概念层面的分析已经完成可以进入关系模型设计了。4. ER图转关系模型实训报告和面试都绕不开的转化规则ER图转化为关系模型是实训报告和作业里必写的步骤也是面试题里反复出现的内容。很多同学卡在这一步本质上是对转化规则不够理解。这里把三条核心规则讲透。4.1 三条转化规则实体成表、外键承接联系、多对多拆中间表规则一每个实体转换成一张关系表实体的属性转换成表的字段实体的主键作为表的主键。这条最简单按实体属性清单建表即可没有太多可说的。唯一需要注意的是主键的生成方式业务主键用字符串如读者编号R001还是自增整数ID实训项目两者皆可但要统一不要一半表用自增、一半表用业务编码。规则二1对1和1对N联系通过增加外键来实现。1对N联系的处理方式是在N端加外键。比如出版社和图书的1:N联系在图书表里增加出版社编号字段作为外键。1对1联系的处理方式灵活一些可以在任意一端加外键实操中一般把外键加在访问频繁或数据量更大的一端。比如用户—用户详情这种1对1通常在详情表里加用户ID外键。规则三M对N联系必须拆成独立的关系表表里包含两端的主键以及联系自身的属性。读者和图书的M:N联系如果直接建外键无论外键放哪边都没法表达一本书被多个读者借过这种关系。所以必须建借阅记录表里面含有读者编号和图书编号两个外键再加上借书日期、应还日期、状态等属性。4.2 图书借阅落地示例五张表的完整结构把第3章的ER图按规则转化得到如下表结构这里先不谈用户扩展按核心业务给五张表读者表 readerreader_id主键nameid_typeid_numberphoneemailregister_datestatus图书表 bookbook_id主键titleauthorisbnpublication_datepricetotal_countavailable_countpublisher_id外键→出版社category_id外键→分类出版社表 publisherpublisher_id主键publisher_namecontact_phoneaddress分类表 categorycategory_id主键category_nameparent_id自关联外键借阅记录表 borrow_recordborrow_id主键reader_id外键→读者book_id外键→图书admin_id外键→管理员borrow_datedue_datereturn_datestatus能看到借阅记录表里三个外键分别对应读者、图书、管理员这就是联系实体转化后的典型形态。管理员单独建表后借阅记录通过admin_id记录谁办理的这笔业务后面要统计某个管理员的办理量一条SQL就能查出来。4.3 面试和答辩常见问法以及答题思路面试题里关于ER图转化最多的考法是给一个多对多的业务场景让你写出关系模式或者反过来给几个表让你画出ER图。核心考点就是多对多的拆解。一个高频追问是为什么需要中间表不建中间表行不行回答思路是关系型数据库只能表达表和表之间的1对多关联多对多关系必须通过中间表转换成两个1对多。中间表里除了两端的主键还能存放联系自带的属性。如果不建中间表借书日期、还书状态这些数据就没有地方存放。另一个高频追问是借阅记录表的主键为什么不用复合主键用(reader_id, book_id)当复合主键意味着一个读者对同一本书只能有一条记录但实际借阅场景中读者借完还了再借同一本书是允许产生多条记录的。所以实训项目里借阅记录更合适的主键是独立的borrow_id而不是复合主键。判断依据是业务上是否允许重复联系发生。关于ER图转关系模型还有一个通用做题步骤我总结成五步圈出所有实体标注主键。判断每对实体间的联系及基数。1:1和1:N联系在相应表中加外键字段。M:N联系建立独立关系表放入两端主键和联系属性。检查每个表的主键是否唯一、外键是否指向明确消除冗余。5. 团队分工怎么切ER图阶段的角色划分与接口约定标题里分工这两个字在实训项目里其实比ER图本身更容易翻车。很多小组习惯于数据库同学画ER图其他人等图出来再干活结果画图的同学既当分析师又当设计者其他人全程围观等到评审的时候一堆人提意见画图的人改到崩溃。5.1 反面案例一个人画图全班等是最差的分工方式带实训时我看到过这样的真实情况小组里A同学负责数据库抱着需求文档闷头画了两天ER图画完发到群里让大家确认。结果B同学说这里读者和图书应该是多对多吧C同学说管理员不用单独建实体吧A又改了一版。到了建表阶段D同学说借阅记录表为什么有三个外键A要重新解释一遍。整个流程特别低效问题的根源就是ER图阶段没有把全员拉进来参与。合理的做法是ER图阶段全员参与但角色分工不同。每个人都要看需求但对不同模块负责程度不一样。我把角色分成四类角色人数职责需求梳理人1把需求文档拆成功能清单和数据需求清单输出候选实体集ER图主笔2根据候选实体集画ER图区分等级并整理说明评审人全员从业务角度校验实体、属性、联系是否合理记录人1把评审结论、争议点和修改记录整理成文档实训项目的组员规模一般是4到6人这个角色分配能保证每个人有具体任务同时又不会出现有人完全没参与建模讨论。5.2 按业务域拆分实体清单各画各的再合并实体比较多的时候一个人握着所有实体画容易顾此失彼而且画到后面会越画越乱。我建议按业务域拆分把实体清单分成几组不同组员负责不同的域。以图书借阅系统为例拆分成三个域读者管理域读者、借阅证若有、罚款记录。图书管理域图书、出版社、分类。流通管理域借阅记录、预约记录、续借记录。三个人各画自己负责的域的局部ER图画完后开一次合并会议。合并时主要做三件事统一实体命名、核对跨域联系、检查是否有遗漏实体。跨域联系是合并时的重点比如借阅记录同时连接读者域的读者和图书域的图书属于流通域但它引用了另外两个域的实体的主键。合并会议就要明确跨域引用的接口字段是什么、命名是否一致比如读者主键在读者域叫reader_id流通域也要叫reader_id不能一会儿readerId一会儿读者编号。时间节奏上我通常建议实训小组按这样的节点推进时间任务产出第1天需求分析圈名词列候选实体实体候选清单第2天分域画局部ER图3份局部ER图第3天合并会议统一命名和联系完整ER图初稿第4天评审、修改、定稿最终ER图和实体属性说明这个节奏不是死规定但至少要有明确的里程碑。没有截止时间的ER图阶段往往会拖到编码前最后一天才草草完成。5.3 统一规范命名、主键、评审这三点提前约定以下几个规范必须在画图开始前就定下来否则中间一改就是连环修改。命名规范方面实体名一律用单数名词比如book而不是books。字段名统一用下划线命名如register_date。类型用integer、varchar、date这样的统一定义。这些规定看起来琐碎但能在合并时省掉大量的对齐工作。主键规范方面每个实体必须设计主键不能出现感觉应该有个ID但还没确定的情况。建议统一用编号字符串或自增整数避免有的表用业务编码、有的表用自增导致后面关联查询时类型不一致。评审机制方面我们实训里用的是两轮评审第一轮画图人自讲全员从业务角度挑刺比如管理员这个实体到底有没有独立存在的必要罚款到底是属性还是实体第二轮按关系模型转化后的表结构再过一遍检查外键是否引用明确。两轮评审后定稿之后进入建表阶段尽量不做大的结构变更。6. 画图工具选型从白板草稿到团队协作的落地选择ER图分析阶段用什么工具画看着是个小事实际上影响不小。选错了工具光是同步和多端打开就够折腾的。6.1 草稿阶段白板和纸笔永远是最快的讨论工具画ER图的前半程我强烈建议用白板或者A4纸。它的优势不是美观而是修改成本极低。三个人围在白板前争论读者和图书到底是M:N还是1:N的时候拿白板笔涂改几下就能换一种表达远比每个人在自己电脑上通过协同工具改来得高效。实操中我会先让团队在白板上画出实体框用几条线把联系连出来。这个阶段只看结构和争议不去美化框线也不管字体对齐。等实体、属性、联系都讨论清楚了再进入电子工具做正式版本。6.2 团队协作工具draw.io和ProcessOn怎么选进入正式版本阶段工具选择要满足几个条件免费或低价、支持多人协作、能导出图片嵌入实训报告。draw.io现在叫diagrams.net是我用得最多的。它免费、免登录也能画实体、联系用现成图形拖拽即可文件可以存在本地也可以存Google Drive或GitHub导出PNG、SVG都方便。缺点是初始界面略朴素但画ER图完全够用。ProcessOn的优点是对国内网络友好、模板丰富搜ER图能找到大量现成模板直接改上手门槛比draw.io还低。缺点是免费版有文件数量限制团队多人协同免费版体验有限导出也有水印或数量限制。我的建议是人多的实训小组用draw.io文件让一位同学统一管理其他人通过在线链接查看和评论如果大家喜欢有模板参照用ProcessOn也可以但提前确认免费版够不够用。6.3 Navicat和MySQL Workbench的逆向ER图物理模型不等于概念模型很多同学搜索mysql的表导出er关系图或navicat画er图实际上是想把已经建好的表一键生成ER图用于实训报告或答辩PPT。Navicat的用法很简单打开模型Model功能新建模型后从数据库导入表表之间的外键关系会自动生成线。MySQL Workbench则是在菜单栏选Database点Reverse Engineer按向导选择数据库连接和库完成后生成一张EER图。这种从表结构逆向生成的图严格来说是数据库表关系图物理模型不等于业务层面的ER图概念模型。二者的区别在于物理模型展示的是字段和外键概念模型展示的是实体和业务联系。实训报告里最好两张图都有——概念模型证明你做了业务分析物理模型展示落地实现这样结构才完整。在实训答辩时如果老师问你的ER图和表关系图有什么区别能答出这两个层次的区别会是很加分的点。7. ER图实战中的高频踩坑这些教训每年实训都能见到这一部分写的是我做实训辅导这几年里反复遇到的典型问题每一条都有真实的反面教材希望后面做项目的人能提前避开。7.1 坑一把联系当实体画把实体当属性画有个小组在画预约借书业务时直接画了一个叫做预约的菱形连接读者和图书没有给它设计任何属性。等到转关系模型的时候发现预约时间预约状态失效日期这些数据没有地方放又回头在菱形外挂一堆属性最后这个菱形实际上承担了实体的职责本质上应该拆成一个预约记录实体。区分方法很简单如果一个联系本身有需要记录的数据项它就应该作为联系实体来处理。联系实体在ER图中既表达联系又有属性转关系模型时直接变成一个独立表这是最规范的方式。另一个方向的问题是把实体降级为属性。比如有人把出版社作为图书的一个属性字段画图阶段觉得省事了但后来想查每个出版社出版了多少本馆藏图书时发现按文本字段group by确实也能查但出版社改名、合并时根本没法维护。属性能否升级为实体判断标准我前面提过它是否有子属性是否被多个实体共享。满足任何一条都应该独立成实体。7.2 坑二同书多副本的业务细节没有建模图书借阅系统有个典型业务细节经常被忽略同一本书图书馆往往有多个副本比如十本《活着》。一种设计是图书表里一条记录对应一个品种馆藏总量10本另一种是一条记录对应一个物理副本每本书一个编号。如果按品种建模借阅记录里的book_id指向的是品种那同一品种的10本被借出时需要在借出时扣减available_count归还时加回来。这种方案的问题是并发场景下容易超借需要事务和状态校验。如果按副本建模每本书从采购入库起就有唯一的book_id读者借到的是具体哪一本清清楚楚。缺点是同一品种的书在书架上会有多条记录图书检索时需要按书名分组展示。实训项目里我建议按品种可借数量来建简单直接答辩时能把这个取舍理由讲清楚也能加分。如果你要挑战更复杂的方案按副本建模也完全可以但要在ER图上体现品种和副本两个实体并明确它们之间1:N的关系。7.3 坑三评审只看图画得多不多不看业务对不对评审环节如果只是大家看一眼这张图画得挺全没什么问题那评审就失去了意义。无效评审最大的特征是只核对了实体数量没有逐条核验业务规则。我列一个评审检查清单照着过一遍基本不会漏每个实体有没有明确主键主键字段是否能唯一标识一条记录每一个联系你都能不能用一句业务话术描述出来比如一个读者可以产生多条借阅记录一条借阅记录只属于一个读者。有没有列出联系基数的反面例子比如问同一个读者同一时间能不能借同一本书两次这个问题的答案决定了借阅记录表的主键是独立编号还是复合主键。属性里有没有冗余字段冗余字段如果在备注里说明用法是可以接受的如果没有任何解释后期维护会一头雾水。所有外键是否都来自某个实体的主键外键字段名是否统一把这份清单打印出来评审时逐条打钩比一堆人围着图热烈讨论要高效得多。7.4 给后面实训的一点个人经验如果让我用一句话总结ER图阶段的要点那就是ER图不是文档负担而是整个项目的第一份设计合同。团队里每个人都应该在动笔写代码前对这份合同达成共识。图画得越仔细后面的开发、测试、答辩都越顺畅。另外提醒一个小细节最终定稿的ER图不代表项目过程中就不改了。实际开发中因为需求变更或发现新问题ER图会被反复微调。每调整一次记得同步更新关系模型和表结构文档不要让ER图和实际数据库越漂越远。答辩时如果老师拿你交的ER图和数据库实际表结构对比发现对不上那才是真的尴尬。做实训项目本来就是在错误中学习的过程ER图分析这关过好了后面的路会顺很多。至少我见过的项目里凡是ER图阶段认真开过评审会的小组代码阶段几乎没有人再回头改表结构。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。