🗄️ 第五章 引入数据库-数据库的结构与表的设计
📄 一句话概括

第三范式(3NF):非主键列之间不许互相依赖——非主键列 B 依赖另一个非主键列 A(A→B 的从属链),就把 A 和 B 一起搬走另立门户。这消灭的是「传递依赖」。

📝 本节和前面几节的关系

三台阶最后一阶,收拾 2NF 管不到的场合:单列主键表里,非主键列之间互相「抱团」。到达 3NF,业务表设计基本达标(5-10 的工程口径)。

一、问题表:列抱团

学生(学号 PK, 姓名, 系, 系电话)

依赖链:学号 → 系 → 系电话(电话传递地依赖学号)。

二、传递依赖的两宗罪

三、整改:抱团的家伙一起搬走

students(学号 PK, 姓名, 系 FK)
departments(系 PK, 系电话)      ← A 和 B 一起搬走,A 当主键

3NF 动作=找出「非主键 → 非主键」的依赖,把后者整族搬进新表,原表留外键。

四、动手 Demo:改一行的诱惑

-- 违规:电话抄在每个学生行里
CREATE TABLE bad_stu (id INT PRIMARY KEY, name VARCHAR(20), dept VARCHAR(20), dept_tel VARCHAR(20));
INSERT INTO bad_stu VALUES (1,'甲','数学','8801'),(2,'乙','数学','8801'),(3,'丙','外语','8802');
-- 数学系换电话:UPDATE 改 2 行(200 人呢?漏一行就是两个版本)

-- 3NF 整改
CREATE TABLE depts (dept VARCHAR(20) PRIMARY KEY, tel VARCHAR(20));
CREATE TABLE good_stu (id INT PRIMARY KEY, name VARCHAR(20), dept VARCHAR(20));
INSERT INTO depts VALUES ('数学','8801'), ('外语','8802');
-- 换电话:UPDATE depts 改 1 行,全系同步

五、30 秒实验

检查 orders(订单号 PK, 客户id, 客户姓名):客户姓名认谁?(认客户 id——非主键依赖非主键,传递依赖!)整改:客户姓名搬进 customers 表,订单表只留 customer_id 外键。这正是 5-10 Demo 里那张订单表的样子。

六、常见误区

自测三问 1. 3NF 消灭什么?(传递依赖——非主键列依赖另一个非主键列) 2. 依赖链怎么读?(学号→系→系电话,电话传递依赖学号) 3. 整改动作?(A、B 整族搬进新表,A 当主键,原表留外键)

相关笔记