实体关系模型(ER)
实体关系模型(Entity-Relationship Model)是用图形化的方式描述现实世界的数据结构——实体是"东西",关系是"联系",是数据库设计的第一步
🤔 如果让你设计一个选课系统——你从哪里开始?
假设学校让你设计一个新的选课系统数据库。你坐在电脑前,打开 MySQL,正准备写 CREATE TABLE 时——突然发现一个问题:
你应该建几张表?每张表里有什么列?表之间怎么关联?
如果直接开始写 SQL,大概率会出现这些状况:
- 写了一半发现漏了一个字段,要回头改表结构
- 设计完发现数据冗余严重,同样的信息要存好多遍
- 上线后发现想查的数据拆不到
这就像盖楼之前没有设计图纸——直接砌砖的结果往往是返工。
🏗️ 类比:盖楼先画设计图
你不会让施工队直接开始砌砖——你得先有设计图:哪里是承重墙、哪里是走廊、房间怎么分布。
ER 图(Entity-Relationship Diagram)就是数据库的”建筑设计图”。 在写一行 SQL 之前,先用 ER 图把”有哪些数据、它们之间有什么关系”画清楚。
🎨 ER 模型的核心三要素
ER 模型只有三个基本概念,但却能描述几乎任何一种现实世界的数据场景:
① 实体(Entity)——“东西”
实体是现实世界中可以独立存在的事物,用矩形表示。
在选课系统中,实体有:
- 学生——每个学生是一个独立个体
- 课程——每门课是一门独立的课程
- 教师——每位老师是一个独立个体
- 教室——每个教室是一个物理空间
判断一个东西是不是”实体”,有个简单的标准:你能不能数出它的具体个数? 能 → 是实体。“学生”不是(泛指概念),但”张三这个学生”是。
② 属性(Attribute)——“特征”
属性是实体拥有的特征,用椭圆表示。
“学生”这个实体的属性:学号、姓名、性别、出生日期、班级……
其中能唯一标识一个实体的属性叫作主键(Primary Key),在 ER 图中用下划线标出。
姓名
│
学号───(学生)─── 班级
(主键) │
出生日期
③ 关系(Relationship)——“联系”
关系描述实体之间的联系,用菱形表示。
学生和课程之间存在”选课”关系——学生选课程,课程被学生选。
(学生)───── 选课 ─────(课程)
🔗 三种关系类型
实体间的联系分为三种,这是 ER 建模中最关键的概念:
1️⃣ 一对一(1:1)
一个实体最多对应另一个实体中的一个,反过来也一样。
人 ──── 身份证
- 一个人最多有一个身份证号码
- 一个身份证号码最多对应一个人
这在数据库设计中比较少见。学生和学号算吗?算——但学号通常是学生的”属性”而不是独立实体。
2️⃣ 一对多(1:N)
一个实体可以对应另一个实体中的多个。
班级 ──── 学生
- 一个班级有多个学生
- 但一个学生只属于一个班级
这是最常见的类型之一。再比如:
作者 ──── 文章 (一个作者写多篇文章)
课程 ──── 上课记录 (一门课程有多次课)
3️⃣ 多对多(M:N)
一个实体可以对应另一个实体中的多个,反过来也一样。
学生 ──── 课程 (通过"选课")
- 一个学生可以选择多门课程
- 一门课程可以被多个学生选择
这是另一个常见类型。注意:多对多关系在数据库中无法直接实现——你需要拆成两个”一对多”。具体怎么拆?直接说答案:引入一个中间表(选课记录表),后面关系模型部分会详细解释。
🚌 类比:公交车线路和站点
一对一 = 你的座位号(一个座位对应一个人,一个人对应一个座位)
一对多 = 一条公交线路有多个站点(一条线路→多个站点)
多对多 = 公交线路和站点的关系——一条线路经过多个站点,一个站点有多条线路经过
📋 完整例子:设计选课系统的 ER 模型
让我们一步步画出选课系统的 ER 图:
第 1 步:找出实体
选课系统中明显有:
- 学生(Student)
- 课程(Course)
- 教师(Teacher)
第 2 步:找出关系
- 学生和课程:选课(M:N——一个学生选多门课,一门课被多个学生选)
- 教师和课程:授课(1:N——一个教师教多门课,但一门课通常只有一个主讲教师)
第 3 步:找出每个实体的属性
- 学生:学号(主键)、姓名、班级、入学年份
- 课程:课程号(主键)、课程名、学分、学时
- 教师:工号(主键)、姓名、职称、所属院系
第 4 步:画出完整的 ER 图
姓名 班级
│ │
学号────(学生)──── 入学年份
│
│ M
│
(选课)
│ N
│
课程号───(课程) 工号───(教师)
│ │ │ │
课程名 学分 姓名 职称
│
学时
│
│ N ↑
(授课)──────────│ 1
注意”选课”关系还有一个自己的属性:成绩—— 成绩既不属于学生(不是学生本身的特征),也不属于课程(不是课程本身的特征),而是”选课”这个关系的属性。这在 ER 建模中很常见。
(学生)───── 选课(成绩)──────(课程)
🧠 为什么不能跳过 ER 建模直接写 SQL?
很多初学者觉得画 ER 图很麻烦——“反正最终都要写成表,为什么不直接建表?”
原因很简单:
坏例子:直接建表
CREATE TABLE 选课 (
学号 INT,
学生姓名 VARCHAR(50),
学生班级 VARCHAR(20),
课程号 INT,
课程名 VARCHAR(100),
学分 INT,
教师姓名 VARCHAR(50),
成绩 INT
);
这张表把所有数据塞进了一张表——三秒建好,但问题一堆:
- 冗余:同一个学生的姓名在每门选课记录里重复存
- 更新异常:学生转班了,要改所有相关行的班级字段
- 插入异常:新开了一门课但还没人选——课程信息存不进去(因为没有学生)
- 删除异常:删除某个退课学生的记录,可能把课程信息也删没了
好例子:先画 ER 图再建表
通过 ER 建模,你会自然而然地拆成多张表:
- 学生表(学号、姓名、班级)
- 课程表(课程号、课程名、学分)
- 选课记录表(学号→外键、课程号→外键、成绩)
- 教师表(工号、姓名、职称)
这样每个数据只存一份,不存在冗余和异常问题。
📝 小结
| 概念 | 一句话 |
|---|---|
| 实体(Entity) | 现实世界中的”事物”,用矩形表示 |
| 属性(Attribute) | 实体的”特征”,用椭圆表示 |
| 关系(Relationship) | 实体间的”联系”,用菱形表示 |
| 1:1 | 一对一(一个身份证对应一个人) |
| 1:N | 一对多(一个班级有多个学生) |
| M:N | 多对多(学生选课),需拆成两个 1:N |
🎯 核心原则:先画清楚再写代码。 ER 图是数据库的设计蓝图——它让你在设计阶段而不是实现阶段发现问题。
为什么先学这个? ER 模型是数据的”概念设计”,但计算机不能直接理解 ER 图。下一步是把 ER 图转化为数学化、可计算的模型——关系模型与关系代数。