先说结论:多端保存一端主键,最自然
一对多关系转换成关系模式时,通常把“一”端实体的主键放到“多”端实体表中,作为外键。比如一个客户可以有多个订单,一个订单通常只属于一个客户,那么订单表里保存客户编号,这个客户编号就是外键。
为什么不是把所有订单编号都放到客户表里?因为客户可能有很多订单,如果在客户表里塞一串订单编号,就会变成重复值和非原子字段,查询、更新、删除都麻烦。关系表更喜欢一行一条清楚记录,所以让每条订单记录自己保存所属客户。
| 场景 | 一端 | 多端 | 外键通常放在哪里 |
|---|---|---|---|
| 客户和订单 | 客户 | 订单 | 订单表保存客户编号 |
| 部门和员工 | 部门 | 员工 | 员工表保存部门编号 |
| 班级和学生 | 班级 | 学生 | 学生表保存班级编号 |
| 出版社和图书 | 出版社 | 图书 | 图书表保存出版社编号 |
判断多端,不靠表名,靠题干里的数量词
考试题最喜欢用“一个”“多个”“只能”“可以”来暗示基数。看到“一个部门有多个员工,一个员工只能属于一个部门”,多端就是员工;看到“一个客户可以下多个订单,一个订单对应一个客户”,多端就是订单。
不要凭业务感觉乱猜。比如“老师”和“课程”有时是一对多,有时是多对多,要看题干说法:一门课是否只能由一名老师讲?一名老师能不能教多门课?这些约束不同,转换结果也不同。
一个更像考题的读法
题干:一个部门可以有多个员工,每个员工只能属于一个部门。
判断:部门是一端,员工是多端。
转换:员工(员工号, 姓名, 部门号),其中部门号引用部门表。
提醒:不是在部门表里写一个“员工列表”字段。
外键放多端,本质上是在表达归属关系
外键不是为了让表结构看起来复杂,它是在表达“这条记录归属于哪条父记录”。订单表里的客户编号,说明这笔订单属于哪个客户;学生表里的班级编号,说明这个学生属于哪个班级。
如果多端记录允许暂时没有归属,还要结合业务判断外键能否为空。比如员工入职后必须属于部门,部门号就应该必填;某些资源暂未分配给项目,项目编号可能允许为空。软考通常不会让你纠缠实现细节,但会考你是否理解外键和参照完整性。
| 问题 | 判断方向 | 容易错在哪里 |
|---|---|---|
| 谁保存外键 | 多端保存一端主键 | 把多个编号塞进一端表 |
| 外键引用谁 | 引用一端表的主键或候选键 | 随便引用普通属性 |
| 能否为空 | 看多端是否必须参与联系 | 不看业务约束 |
| 删除一端记录 | 要考虑多端是否仍引用 | 忽略参照完整性 |
和一对一、多对多放在一起记
一对多的规则相对稳定:外键放多端。多对多通常要单独建联系表。一对一则要看参与约束、访问习惯和是否适合合并。把这三类放在一张表里比较,比单独背一句口诀更牢。
如果你后面要继续练数据库设计题,可以先用本站看 ER 图转换规则,再去书木兰软考题库按章节刷数据库设计和软件设计师相关题,网址是 https://www.shumulan.com/。这类题刷题时最重要的是每道题都说清“为什么这样建表”。
相关题目解析
下面这些题目和本专题的判断方法关联较强,适合读完概念后回到具体题干里校验理解。
- ER 图一对多联系转换成关系表时外键放在哪里?ER 图 / 关系模式转换
- 外键约束为什么能维护参照完整性?外键约束 / 参照完整性
- 数据库表中的主键为什么不能重复也不能为空?主键 / 实体完整性