一张表要算是第二范式,得满足:
- 它已经在第一范式(1NF)里了。
- 每个非主键列都依赖于整个主键,而不是只依赖主键的一部分。
如果主键是由多个字段组成(复合主键),那任何非主键属性(列)都不能只依赖主键的一部分。换句话说,2NF就是要消除部分依赖。
2NF被破坏的例子
假设我们有个表student_courses(学生和课程),它存着学生、他们的课程和老师的信息:
| student_id | course_id | course_name | instructor_name |
|---|---|---|---|
| 1 | 101 | 数学 | Lin |
| 1 | 102 | 文学 | Song |
| 2 | 101 | 数学 | Lin |
student_id和course_id一起组成复合主键。- 但注意
course_name和instructor_name这两列。它们只依赖course_id,而不是整个(student_id,course_id)组合。
这就是部分依赖!course_name和instructor_name只依赖复合主键的一部分(course_id)。这就违反了2NF的原则。
让表格达到2NF
我们的目标——消除部分依赖,把表拆成两张。这样能去掉冗余,让数据更一致。
把课程相关的信息单独拎出来做一张courses表:
| course_id | course_name | instructor_name |
|---|---|---|
| 101 | 数学 | Lin |
| 102 | 文学 | Song |
主表就变成这样:
| student_id | course_id |
|---|---|
| 1 | 101 |
| 1 | 102 |
| 2 | 101 |
现在每一列都依赖整个主键了。我们把数据分开,逻辑更清晰,也消除了2NF的违规。
消除冗余的魔法
注意看规范化前的表。instructor_name这一列里"Lin"出现了好多次。现实数据库里有成千上万条记录,这种重复会更多。拆表后,冗余没了,出错(比如"Lin"和"Ling"拼错)的概率也低了。
生活中的例子
想象你在做商品订单管理。有个order_items表(订单和商品),order_id和item_id是主键:
| order_id | item_id | item_name | price |
|---|---|---|---|
| 1 | 101 | 笔记本电脑 | 50000 |
| 1 | 102 | 鼠标 | 1000 |
| 2 | 101 | 笔记本电脑 | 50000 |
你看,商品名和价格都在重复。这就是2NF被破坏的信号,因为item_name和price只依赖item_id。
要让表格达到2NF,我们建个items表:
| item_id | item_name | price |
|---|---|---|
| 101 | 笔记本电脑 | 50000 |
| 102 | 鼠标 | 1000 |
再把order_items表改成只留订单和商品ID:
| order_id | item_id |
|---|---|
| 1 | 101 |
| 1 | 102 |
| 2 | 101 |
现在数据干净得像代码review后一样——没有冗余。
实战练习:你来试试!
假设你有个employee_projects表,存着员工、他们的项目和项目经理的信息:
| employee_id | project_id | project_name | manager_name |
|---|---|---|---|
| 1 | 201 | CRM升级 | Lin |
| 2 | 202 | 网站改版 | Ming |
| 1 | 202 | 网站改版 | Ming |
试试看:
- 找出哪些依赖违反了2NF。
- 把表拆成两张,消除违规。
为什么要遵守2NF?
为啥要遵守第二范式(2NF)?很简单:为了不让数据重复,避免混乱。消除部分依赖后,表格更干净——不会有一堆重复的信息,比如每行都写一遍老师名字。这样省空间,也不怕数据不一致:只要一个地方改名字,所有地方都同步了。
而且,这样的数据库写查询也更爽:结构清晰,数据不分散,过滤和分组都快又稳。确实,表多了点,SQL里JOIN多了点,但总比一堆重复的名字强。大多数时候,规范化绝对值。
和实际项目结合
2NF的知识你会用到:
- 设计数据库时:帮你避免表格乱成一锅粥。
- 面试时:经常会让你解释或者把表规范化。
- 实际工作中:当你要优化现有数据库,把“大杂烩”表拆成规范化的表时。
第二范式(2NF)就是帮你消除复合主键表里的部分依赖。我们把表拆成逻辑块,让每列只依赖整个主键,而不是主键的一部分。这样数据库质量更高,冗余没了,灵活性也提升。准备好学第三范式了吗?继续冲!
GO TO FULL VERSION