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

第一范式(1NF):每一格只装一个值——不许逗号串、不许「商品2/商品3」式重复列。它是关系的入场券:不满足 1NF 的表根本不算关系型表。

📝 本节和前面几节的关系

规范化(5-10)三台阶的第一阶,也是最硬的一条:0 條件不满足,后两条免谈。它还给第三章的 >>/LIKE 查询报了仇——逗号串存的值,检索起来是灾难。

一、两种典型违规

违规一:一格多值(逗号串)

学生(学号, 姓名, 选修课)
     1    张三   "数学,英语,物理"     ← 一格塞三门课

后果:想查「谁选了数学」只能 LIKE '%数学%'(3-10 的 LIKE 被迫营业);想统计选修人数?没门。

违规二:重复列

学生(学号, 姓名, 选修课1, 选修课2, 选修课3)

后果:最多记三门?第四门来了加列改表(伤筋动骨);统计空列、对齐列全靠人肉。

二、整改:重复组拆出去,一行一格

students(学号 PK, 姓名)
enrollments(学号 FK, 课程名)      ← 一行一条选修记录

1 张三
1 数学 / 1 英语 / 1 物理          ← 三行,一格一值

这就是 5-6 中间表手法的又一现身——重复组的天敌就是「拆出去变行」。

三、动手 Demo:逗号串之痛

CREATE TABLE bad (id INT, name VARCHAR(20), courses VARCHAR(100));
INSERT INTO bad VALUES (1, '张三', '数学,英语'), (2, '李四', '物理,化学');

-- 谁选了数学?只能模糊匹配
SELECT * FROM bad WHERE courses LIKE '%数学%';

-- 隐患:再来一门「高等数学」,LIKE '%数学%' 也会命中——误伤!

规范化版:

CREATE TABLE good (id INT, course VARCHAR(20));
INSERT INTO good VALUES (1,'数学'),(1,'英语'),(2,'物理'),(2,'化学');

SELECT id FROM good WHERE course = '数学';   -- 精确命中,只有张三

四、30 秒实验

给 bad 表统计「选数学的人数」:COUNT 无从下手,只能逐行数字符串。给 good 表:SELECT COUNT(*) WHERE course='数学' 一发命中——1NF 不是洁癖,是统计功能的前提。

五、常见误区

自测三问 1. 1NF 的要求?(每格恰一个值,禁逗号串禁重复列) 2. 逗号串查「精确等于某值」为什么危险?(LIKE 误伤子串——数学 vs 高等数学) 3. 重复组的正解?(拆出去变行——中间表)

相关笔记