vault backup: 2026-05-20 00:00:48
This commit is contained in:
@@ -40,16 +40,21 @@ CREATE TABLE employees (
|
||||
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
name VARCHAR(100),
|
||||
phone VARCHAR(20), -- 单一手机号
|
||||
skills JSON -- 数组存在 JSON 字段内
|
||||
skills JSON -- 数组存在 JSON 字段内(如 ["Go","Python"])
|
||||
);
|
||||
|
||||
-- ❌ 违反 1NF:同一列存多个值(用逗号分隔)
|
||||
CREATE TABLE bad_employees (
|
||||
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
name VARCHAR(100),
|
||||
skills VARCHAR(255) -- 'Go,Python,Docker' — 不行!
|
||||
skills VARCHAR(255) -- 'Go,Python,Docker' — 不行!无法单独查询某个技能
|
||||
);
|
||||
```
|
||||
|
||||
> [!TIP] 现代变通方案
|
||||
>
|
||||
> MySQL 5.7+ 支持 JSON 类型。虽然从严格范式角度看 JSON 列内部仍有复合结构,但数据库引擎提供了高效的索引和查询能力(如 `JSON_EXTRACT`),所以在工程实践中被广泛接受。**核心原则不变:不要把非结构化数据当字符串拼接处理。**
|
||||
|
||||
1NF 是最基本的要求——每一列都是原子值,不能再拆分。现代关系型数据库默认强制执行 1NF。
|
||||
|
||||
### 第二范式(2NF)—— 消除部分函数依赖
|
||||
@@ -133,6 +138,23 @@ CREATE TABLE student_course_teachers (
|
||||
);
|
||||
```
|
||||
|
||||
```sql
|
||||
-- ✅ 修正为 BCNF:拆成两张表,让每个决定因素都是超键
|
||||
CREATE TABLE courses_teachers (
|
||||
course_id BIGINT PRIMARY KEY,
|
||||
teacher_id BIGINT NOT NULL,
|
||||
UNIQUE KEY uk_course (course_id) -- 一门课只有一位老师
|
||||
);
|
||||
|
||||
CREATE TABLE student_grades (
|
||||
student_id BIGINT,
|
||||
course_id BIGINT,
|
||||
grade DECIMAL(5, 2),
|
||||
PRIMARY KEY (student_id, course_id),
|
||||
FOREIGN KEY (course_id) REFERENCES courses_teachers(course_id)
|
||||
);
|
||||
```
|
||||
|
||||
> [!QUESTION] 3NF 已经够了,为什么还需要 BCNF?
|
||||
>
|
||||
> 大多数工程场景 3NF 完全够用。BCNF 解决的问题通常涉及**多重候选键重叠**的复杂建模。如果你遇到 "一门课只能由一位老师教" 这样的约束,且该约束与你的自然主键冲突,才需要考虑 BCNF。实践中建议先做到 3NF,遇到更新异常再往上走。
|
||||
@@ -142,6 +164,19 @@ CREATE TABLE student_course_teachers (
|
||||
>
|
||||
> 但这恰恰是现代工程实践的真相:我们用自增代理主键保证查询性能,用外键语义保证设计合理。**范式检查应该在业务层(逻辑模型)上做,而不是在物理表结构上硬抠。**
|
||||
|
||||
## 三范式速查总结
|
||||
|
||||
读完上面的详细内容,回头用这张表做最后的对比和记忆强化:
|
||||
|
||||
| 范式 | 核心问题 | 违规症状 | 一句话修复 |
|
||||
|------|---------|---------|-----------|
|
||||
| **1NF** | 列是不是原子值? | 一格里塞了多个值 | 拆成多行或多列 |
|
||||
| **2NF** | 这列依赖主键的**全部**吗?(仅复合 PK 场景) | 某些列只依赖主键的一部分 | 把只依赖部分的列拆到新表 |
|
||||
| **3NF** | 这列有没有**绕道**经过其他非主键列? | B 列的值由 C 列决定,而不是直接由主键决定 | 把 C 列及它决定的所有列拆出去 |
|
||||
| **BCNF** | 每个决定因素都是超键吗? | 候选键之间有重叠,约束冲突 | 拆到没有交叉候选键为止 |
|
||||
|
||||
---
|
||||
|
||||
## 表设计实操流程
|
||||
|
||||
知道范式定义是一回事,拿到需求画出一张合理的 ER 图是另一回事。这里给一个**四步工作流**:
|
||||
|
||||
Reference in New Issue
Block a user