资讯详情 数据库ER图习题PDF:从实体、关系到建表SQL的建模全攻略
📅 2026/10/9 17:22:43
简介数据库ER图习题.pdf是一份面向数据库初学者与备考学生的ER图概念模型练习资料。资源为单个PDF文件大小仅83KB轻量易存适合零碎时间刷题。资料汇集了一批典型ER图设计题目场景覆盖商业库存与销售、汽车运输、银行储蓄、体育锦标赛、高校教务、医院住院管理、证券营业和旅游管理等每一题都给出了实体、属性及联系解析重点说明如何将真实业务规则转化为实体间的一对多、多对多关系并标注“库存”“供应”“聘用”“隶属”等联系的关键属性。已有2311人学习下载适合正在学习数据库设计、考研复习或备战期末考试的读者使用。通过对照题目与解析反复练习可有效提升从需求描述中识别实体、提炼属性、梳理联系的建模能力为后续关系模式设计与SQL实现打好基础。1. 数据库ER图习题PDF先把这份资源能解决的问题说透数据库设计这片领域里ER图从来不是“画个矩形、拉条线”那么轻松。真正决定建模对错的是你能不能从一段业务描述里认出哪些词该立成实体、哪些词只能当属性以及两个实体之间的基数比到底是几比几。网上流传的这份数据库ER图习题PDF不是教材也不是工具而是一份把常见业务场景压成小小题目的训练集。它解决的问题非常具体让你把零散的文字需求翻译成规范的ER图再把ER图无损转换为关系模式最后落成建表SQL和可执行的查询顺带绕开考试和实际项目中反复出现的那些坑。适合正在备考数据库、要做课程设计或者工作里想系统补一补数据建模基本功的从业者也适合那些已经会写SQL、但一碰到“多对多关系怎么建表”就犯怵的人。2. 实体、属性与联系读懂习题里的三种核心建模元素拿到一份ER图习题第一步不是急着找矩形和菱形而是先在题干里把“实体、属性、联系”这三类东西分开。很多题目的丢分点恰好就藏在这层分类里同一个词在A题里是实体在B题里就只是属性。判断标准并不是词的形态而是题干有没有围绕这个概念展开独立描述。2.1 实体与属性从题干文字里揪出矩形和椭圆我习惯用一个很笨但有效的筛选法把一个名词在题干里出现的次数和修饰它的形容词数出来。一个概念出现了三次以上而且它前面挂着“名称、编号、状态”这类描述那它就该画成矩形如果它只是说明某个实体的特征比如“学生的年龄”“图书的价格”那它自然是椭圆里的属性。拿习题里很常见的“某高校学生信息管理系统”来说“班级”这个词如果只是描述学生属于哪个班那它就是学生实体的一个属性但题目一旦再写“每个班级有班主任、教室、人数”班级就该单独立成实体。这个判断直接决定后面表结构里要不要单拆一张班级表。符号、语法和判断信号可以对照下面这张表习题PDF里每一道题都能拿它套图形元素图形符号代表含义判断信号实体矩形独立存在的事物集合有可唯一标识的码有多个描述属性属性椭圆实体的特征挂在某个实体下不单独承担业务逻辑联系菱形实体之间的关联题干中出现“每个”“一个”等对应关系字眼派生属性虚线椭圆可由其他属性计算得到“年龄由出生日期计算”“总分由各科成绩加总”多值属性双线椭圆一个实体对应多个值“一个人有多个电话号码”主码的选择在习题里也是高频考点。学号、身份证这种天然唯一的字段适合做主码姓名、性别这种重复率极高的字段直接排除。有些题故意写“学生有联系电话”但没说一部还是多部这是多值属性的信号正确答案要么拆出“联系电话”表要么用双线椭圆标出绝不能把多个电话号码塞进同一个文本字段里。2.2 联系类型1:1、1:N、M:N 的判定信号与习题特征联系是ER图建模里最值钱的部分。判断基数比的标准动作是向自己提两个问题一个X实体最多对应几个Y实体反过来一个Y实体最多对应几个X实体两个答案都固定是1那是1:1一边固定是1另一边是多个那是1:N两边都是多个那就是M:N。习题题干里通常会藏信号词“每门课程由一位教师讲授”——课程对教师是N:1“每个仓库可以存放多种零件每种零件可以存放在多个仓库”——这是经典M:N“每个部门只有一个负责人每个负责人只负责一个部门”——1:1。判断题做多了你会发现M:N最常出现在“选课”“存放”“借阅”“参与”这几个动作性词汇后面因为这些动作天然需要一张连接表去记录双方的多对多关系同时还能顺手存下动作本身的附加属性比如选课成绩、借阅日期、存放数量。还有一种容易被忽略的题型是一元联系也就是实体自己跟自己发生关联。习题里出现过“员工管理员工”一类的自环联系一个员工管多个下属一个员工只有一个直属上级。这种题在转换成关系模式时处理方式是给员工表增加一个“上级编号”外键指向员工表自身的主键。判定基数的方法和二元联系一模一样只是两个参与方指向同一张实体表。三元联系和“联系带属性”是拉分题。当一个联系本身有值得记录的信息时比如“某个学生选某门课取得某个成绩”成绩属于联系“选课”而不是学生或课程实体。转换关系模式时M:N联系会被独立建成一张选课表成绩列就放在这张表里。习题PDF里这类题目反复出现练的其实就是这个思维习惯——先分清主谓宾再画连线最后决定属性挂在哪一端。3. ER图转关系模式从图形到表结构的四步映射法ER图画得再漂亮最终交付的还是一组关系模式。很多新人在这里踩的第一个大坑是“看图说话”实体转表、属性转列谁都懂但联系到底转成什么教材讲得含糊习题答案又直接跳过推导过程。我一般按下面这套步骤走配合习题PDF练熟以后基本不会漏字段。3.1 普通实体与弱实体一张表对应一个实体的边界条件普通实体转关系模式的规则非常直白实体名变成表名属性名变成列名实体主码变成表主键。真正需要多想一步的是弱实体。弱实体的特征是“离开了某个强实体就无法独立存在”习题里常见的例子是“员工-家属”家属没有全局唯一的编号只有依赖员工工号和家属顺序号才能唯一标识。这种题转换成表时家属表的主键必须是“员工工号 家属序号”的复合主键同时“员工工号”也得作为外键指向员工表。漏掉父实体主键表结构照样能建出来但会造成第五张表里说的存在性依赖丢失问题。3.2 三种联系的转换规则外键放哪不再靠蒙联系转关系模式核心是“外键朝哪个方向放”。三条规则可以覆盖90%的习题联系类型转换规则外键位置注意点1:1并入任意一端实体表选择任一张表添加另一方的主键作为外键建议并入查询频率高的一端1:N并入N端实体表N端表添加1端表的主键作为外键1端表不加外键M:N独立建一张中间表中间表分别持有两端的实体主键中间表可以再放联系属性1:1联系的“并入任意一端”让很多新手纠结其实选哪边在逻辑上都成立真正判断依据是业务查询方向。比如“班级-班主任”这种1:1如果系统里经常从老师查班级就把班级编号放进教师表反过来就放进班级表。1:N最典型的是“仓库-零件”改为“供应商-零件”场景供应商表主键要出现在零件表里而不是反过来。M:N里的中间表专有名词很多连接表、联系表、交叉表说的都是它习题PDF里你还会看到它被叫“选课表”“借阅表”本质都是M:N关系的落地。3.3 完整习题实战一道综合题拆出完整关系模式清单来走一遍习题PDF里我认为最有代表性的综合题它同时包含了1:N和M:N两类联系还带联系属性覆盖面很广。题干每个仓库可以存放多种零件每种零件可以存放在多个仓库存放时记录数量每种零件由唯一的供应商供应仓库有仓库号、面积、电话零件有零件号、名称、规格供应商有供应商号、名称、地址。第一步抽实体仓库、零件、供应商三个矩形。第二步抽属性并定主码仓库号、零件号、供应商号分别做主码。第三步判断联系“存放”是M:N联系附加属性是存放数量“供应”是1:N联系一个供应商供应多种零件但一种零件只有唯一供应商。第四步套规则得到关系模式关系模式字段主键外键仓库仓库号、面积、电话仓库号无零件零件号、名称、规格、供应商号零件号供应商号 → 供应商供应商供应商号、名称、地址供应商号无存放仓库号、零件号、存放数量仓库号 零件号仓库号 → 仓库零件号 → 零件注意零件表里那个“供应商号”它来自1:N联系被并入N端零件是N存放表里的“存放数量”则是M:N联系的属性放不进仓库或零件任何一端只能挂在连接表里。检查阶段的重点是核对每个习题需求是不是都被字段覆盖到了——“按仓库查零件”“按零件找供应商”“查某种零件在某个仓库里存了多少”这三个需求分别落在存放表、零件表、存放表三处没有遗漏。4. 关系模式到建表SQL把设计落成MySQL DDL的完整过程关系模式清单确认后下一步就是把它们变成能跑的建表语句。这里有两个容易让新手卡住的点数据类型怎么选外键约束要不要加。4.1 选类型与写约束仓库零件系统的建表SQL接上一章的清单我一般会写成下面这样CREATE TABLE supplier ( supplier_id CHAR(8) PRIMARY KEY, supplier_name VARCHAR(50) NOT NULL, address VARCHAR(100) ); CREATE TABLE warehouse ( warehouse_id CHAR(8) PRIMARY KEY, area DECIMAL(10, 2), phone VARCHAR(20) ); CREATE TABLE part ( part_id CHAR(8) PRIMARY KEY, part_name VARCHAR(50) NOT NULL, spec VARCHAR(30), supplier_id CHAR(8), CONSTRAINT fk_part_supplier FOREIGN KEY (supplier_id) REFERENCES supplier(supplier_id) ON DELETE SET NULL ); CREATE TABLE storage ( warehouse_id CHAR(8), part_id CHAR(8), quantity INT NOT NULL, PRIMARY KEY (warehouse_id, part_id), CONSTRAINT fk_storage_warehouse FOREIGN KEY (warehouse_id) REFERENCES warehouse(warehouse_id) ON DELETE CASCADE, CONSTRAINT fk_storage_part FOREIGN KEY (part_id) REFERENCES part(part_id) ON DELETE CASCADE );每个表都有它需要解释的地方。supplier_id、warehouse_id、part_id 用 CHAR(8) 而不是 INT 自增是因为习题场景里的编号往往是业务编码比如“SUP001”“WH0001”定长字符串可以保证编码规则一致。part_name、supplier_name 用 VARCHAR(50)名称类字段可变长50个字符通常够用spec 用 VARCHAR(30) 足够容纳“M12×45”这类规格描述。area 用 DECIMAL(10,2) 而不是 FLOAT面积数据要精确到两位小数浮点数在统计汇总时会出玄学级的计算误差DECIMAL不会。quantity 用 INT数量不存在小数。外键的 ON DELETE 策略我专门分开解释part 表引用 supplier 时用 ON DELETE SET NULL意思是供应商删除后零件还在供应商号置空保护业务数据storage 表两个外键都用 ON DELETE CASCADE因为存放记录本身就是依附于仓库和零件存在的孤儿记录没有任何意义。4.2 反向校验把MySQL表结构导回ER图核对答案写好SQL之后我用一个习惯动作来验证建模是否丢东西建完库表后用建模工具做一次“由表还原ER图”。PowerDesigner 这一类的建模工具都支持反向工程连上数据库工具会自动把表之间的外键关系画成连线生成一张可以直接和习题答案对照的ER图。这个动作对带外键的设计最有效因为工具能直观显示出所有关联关系哪种联系被漏掉、哪条外键方向放反了一眼就能看出来。如果手上没有图形化工具也可以用 MySQL 自带的 information_schema 来核对外键关系SELECT TABLE_NAME, COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA your_database AND REFERENCED_TABLE_NAME IS NOT NULL ORDER BY TABLE_NAME;这段SQL把当前库里的所有外键约束列出来看每一行的 TABLE_NAME 和 REFERENCED_TABLE_NAME 是否和关系模式清单一一对应。值得注意的是连接表 storage 会用两个外键分别指向 warehouse 和 part如果你看到了这两个外键记录说明M:N联系落对了。4.3 连接表两种主键策略复合主键与代理主键的取舍M:N连接表的主键设计是个经典二选一。习题里普遍采用复合主键比如 storage 表的 PRIMARY KEY (warehouse_id, part_id)它天然保证了“同一零件在同一仓库只能有一条存放记录”业务上完全吻合。但实际生产项目里尤其在使用ORM框架的项目中连接表常被加一个无意义的自增ID这是出于框架便利性考虑因为很多框架处理复合主键比较别扭。两种策略没有绝对的对错取舍表可以参考策略优势代价推荐场景复合主键防止重复关联查询直接命中ORM兼容性差字段组合较长习题作答、数据需要唯一性约束的库代理主键自增IDORM友好外键引用更短需要另加唯一约束防止重复生产系统、配合ORM框架开发如果选择了代理主键那么连接表的业务唯一性约束必须补上否则同一对仓库-零件会被插入两条内容。正确写法是在连接表上再加一条 UNIQUE KEY而不是只建自增主键不管其他字段CREATE TABLE storage_use_auto_id ( id INT AUTO_INCREMENT PRIMARY KEY, warehouse_id CHAR(8) NOT NULL, part_id CHAR(8) NOT NULL, quantity INT NOT NULL, UNIQUE KEY uk_wh_part (warehouse_id, part_id), FOREIGN KEY (warehouse_id) REFERENCES warehouse(warehouse_id), FOREIGN KEY (part_id) REFERENCES part(part_id) );这条 UNIQUE KEY 承担了原来复合主键的职责UNIQUE 后面括号里那两个字段的先后顺序也有讲究把它定义为 (warehouse_id, part_id)就是按“仓库→零件”的粒度约束唯一性。5. 避坑与自查翻车最多的五个ER图建模错误习题PDF里除了题目更值钱的是你自己做错之后留下的对照记录。我拿身边出现过的大量真实“翻车现场”做了五条归纳每条都是现象、原因、解决三步讲清。5.1 联系外键放错表M:N被硬压成1:N现象学生选课关系里把学生号外键放进了课程表结果课程表里只能存一个学生选修同一门课的第二个人一插入就报错。 原因外键列天然只能表达“一对多”关系M:N关系的两端都需要“多”的概念靠单一外键字段装不下。 解决承认这是M:N必须新建独立的选课表两端各放一个外键选课表用 (student_id, course_id) 做复合主键。这是一个结构性问题改字段长度、调约束都救不了。5.2 派生属性照单全收年龄存进表后逐年失真现象习题里写着“查询年龄大于20岁的学生”有人就在 student 表里存了 age 列。过一年再跑统计之前20岁的学生全部变成了21岁数据还在语义已经错了。 原因年龄是由出生日期计算出来的派生属性存进表里的只是某一个时间点上的快照时间流逝后快照不会自动更新。 解决表里存出生日期查询时实时计算。SQL标准写法是WHERE TIMESTAMPDIFF(YEAR, birth_date, CURDATE()) 20。这符合习题里“不存储可由其他字段推导出的值”的规范也避免以后每年要做一次全表更新。5.3 连接表自增ID好用但业务唯一性约束被忘现象选课连接表加自增ID后同样的 (student_id, course_id) 被插入了两遍后续统计课程人数时count翻倍甚至翻三倍。 原因自增ID是代理主键只保证自身唯一它无法感知业务上不该重复的组合。复合主键消失时原本由它承担的唯一性约束也没了。 解决连接表有代理主键也能用复合唯一索引。在表上补UNIQUE KEY uk_stu_course (student_id, course_id)让数据库从约束层面拦截重复插入而不是靠业务代码先查一遍再插。5.4 弱实体漏挂父实体主键存在性依赖全丢现象员工家属表只设计了家属自身字段没有把员工工号纳入主键结果两个员工的家属可能恰好顺序编号相同数据串到别人头上。 原因弱实体没有全局唯一的标识“家属序号”只在同一个员工下才有效脱离了父实体主键它没有任何区分度。 解决弱实体的主键必须由“父实体主键 判别属性”共同构成。比如家属表主键写成 (emp_id, dependent_id)同时 emp_id 作外键指向员工表。习题中凡是出现“依赖某实体才能存在”的表述都要按这个规则处理。5.5 三元联系基数误判外键数量对不上号现象做“供应商-零件-项目”三元联系题时按两两之间的二元关系转换最后建出来的表要么少外键要么多出好几张多余的连接表。 原因三元联系是三个实体共同决定一条关联不能单纯拆成两两关系来看。每一个组合都需要三方的参与条件一起去约束。 解决先整体建一张三元连接关系表里面放三个外键再把三元联系中存在的局部二元1:N并入对应实体。例如“每个供应商供应多种零件”这个1:N就让零件表带供应商号“供应商和项目的供应关系”仍留在三元表里。先降维、再合并顺序不能反。6. 实例化数据反查法用测试记录验证ER图是否真正成立画完ER图并转成关系模式后我最后永远会做一道工序——实例化反查。方法很简单往每张表里插入两行足够典型的测试数据然后拿题干中的查询需求去写SELECT如果SQL写不出来或者结果明显违背业务逻辑说明ER图在某个环节丢了信息。拿仓库零件系统举例。题干说“查询每个仓库存放的零件总数量”如果 storage 表设计对了这条SQL能一口气跑通INSERT INTO warehouse (warehouse_id, area, phone) VALUES (WH001, 1200.00, 010-12345678); INSERT INTO part (part_id, part_name, spec, supplier_id) VALUES (P001, 水阀, DN50, SUP001); INSERT INTO storage (warehouse_id, part_id, quantity) VALUES (WH001, P001, 200); SELECT w.warehouse_id, SUM(s.quantity) AS total_quantity FROM warehouse w LEFT JOIN storage s ON w.warehouse_id s.warehouse_id GROUP BY w.warehouse_id;两行记录加一条聚合查询就把“仓库和零件是否是M:N”“连接表是否漏了联系属性”“两个主外键是否对齐”三个疑点全部验了一遍。如果这条SELECT跑出来一条空记录你就知道坚决不能开始写业务代码——模型错了后面写什么都白搭。还有一个进阶技巧同一个需求画出两种不同的ER图方案用反查法判断哪种更好。比如“选课成绩”既可以是联系属性也可以把“选课记录”拖出来立成一个实体。两边都能建表但反查“重修补考成绩”时联系属性方案要改表结构实体方案只需要更新一条记录。这种取舍在习题PDF里不会直接写答案但用反查法一测哪种设计扩展性更强就一目了然了。至于那份让自己反查失败的习题我在纸面上把连接表、外键、复合主键全部重画了一遍从那以后我建立了习惯每画完一张ER图都强制走一遍“造记录→写查询→查漏项”的反查流程模型的正确性基本就稳了。希望你也能用这个方法少走几段我走过的弯路。本文还有配套的精品资源点击获取