第三范式(3NF)就是让我们的数据更有条理的一步。简单说,一张表满足3NF,得:
- 它已经在第二范式(2NF)里了。
- 所有非主键属性只依赖于主键,不能依赖别的(不能有传递依赖!)。
换句话说,3NF要求表里的所有数据都得直接和主键相关,不能依赖别的非主键属性。
传递依赖是啥?就是A属性依赖B属性,B又依赖C,这样就有一条链A → B → C。比如,“员工”依赖“部门”,“部门”又依赖“位置”,那“员工”就传递依赖于“位置”。
3NF被破坏的例子
假设我们有一张employees表,存员工信息:
| employee_id | name | department | department_manager |
|---|---|---|---|
| 1 | Otto Lin | Marketing | Leo Zhang |
| 2 | Alex Song | Finance | Maria Chi |
| 3 | Anna Ming | Finance | Maria Chi |
这里:
employee_id— 主键。department和department_manager— 非主键属性。
乍一看没啥问题,但仔细看就有坑:department_manager不是依赖employee_id,而是依赖department。所以就有了传递依赖:employee_id → department → department_manager。
可能遇到的问题
如果我们改了某个部门的经理名字(比如“Finance”),就得把所有这个部门的行都更新一遍。如果漏了一行,数据就不一致了。这种事儿真让人头大,其实完全可以避免。
让表满足3NF
为了去掉传递依赖,我们把表拆成两张:一张存员工,一张存部门。
employees表
| employee_id | name | department |
|---|---|---|
| 1 | Otto Lin | 市场部 |
| 2 | Alex Song | 财务部 |
| 3 | Anna Ming | 财务部 |
departments表
| department | department_manager |
|---|---|
| 市场部 | Leo Zhang |
| 财务部 | Maria Chi |
现在结构清楚了,每张表各管各的:
employees表存员工信息。departments表存部门和经理信息。
如果部门经理换人,只要改departments表里的一行就行,不用改所有员工记录。
怎么判断表破坏了3NF?
想知道表有没有破坏3NF,可以检查:
- 表里有没有传递依赖?比如A属性依赖B,B又依赖C。
- 所有非主键属性是不是都直接依赖主键?如果有依赖别的非主键属性的,那就不是3NF。
实际例子:商店
来看一张sales表,存销售数据:
| sale_id | product_name | product_price | customer_name |
|---|---|---|---|
| 1 | 手机 | 20 000 | Otto Lin |
| 2 | 笔记本 | 50 000 | Alex Song |
| 3 | 手机 | 20 000 | Anna Ming |
这里明显有冗余:商品价格每次销售都重复。如果价格变了,数据立马就不一致了。
为了解决3NF问题,我们把表拆两张:
sales表存销售信息。products表存商品和价格。
sales表
| sale_id | product_id | customer_name |
|---|---|---|
| 1 | 1 | Otto Lin |
| 2 | 2 | Alex Song |
| 3 | 1 | Anna Ming |
products表
| product_id | product_name | product_price |
|---|---|---|
| 1 | 手机 | 20 000 |
| 2 | 笔记本 | 50 000 |
现在如果商品价格变了,只要改products表里的一行,数据就一直是对的。
实战练习
来个小练习:你有一张students_courses表,长这样:
| student_id | student_name | course_name | teacher_name |
|---|---|---|---|
| 1 | Otto Lin | 数学 | Maria Chi |
| 2 | Alex Song | 编程 | Leo Zhang |
| 1 | Otto Lin | 编程 | Leo Zhang |
把这张表拆成3NF。提示:你需要建三张表(students、courses、teachers),并把它们正确关联起来。
为啥要遵守3NF?
为啥要折腾第三范式(3NF)?因为它真的让生活更轻松。表结构规范了,数据就干净——没有多余的重复,出错的机会也少。更新数据也快多了,因为只用改一个地方,不用到处复制粘贴。
而且数据库结构更灵活。想加新字段或者改旧的,不用大动干戈。
不过,和所有好事一样,也有小坑:太极端的规范化会让表变得特别多,查询时JOIN一堆表,可能会慢。所以要有度。该规范化就规范化,能接受点冗余也别怕。
接下来我们会更深入:学会怎么正确建立表之间的关系,做出又方便又靠谱的数据库。冲鸭,数据库设计走起!
GO TO FULL VERSION