📄 一句话概括
第一范式(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 不是洁癖,是统计功能的前提。
五、常见误区
- 「逗号串省表多方便」:方便的是录入那一秒,麻烦的是之后每一次查询、统计、约束
- 「一格一个值就算 1NF 了」:还要消灭重复列(选修课1/2/3)——那是一格多值的横排版
自测三问
1. 1NF 的要求?(每格恰一个值,禁逗号串禁重复列) 2. 逗号串查「精确等于某值」为什么危险?(LIKE 误伤子串——数学 vs 高等数学) 3. 重复组的正解?(拆出去变行——中间表)- ☐ 下一节(5-12 第二范式-拆分其他种类的项目)
相关笔记
- 规范化-统一数据的格式 —— 上一节:三台阶总纲
- 第二范式-拆分其他种类的项目 —— 下一节:第二台阶
- IN、LIKE、IS NULL-用于查询的符号2-包含值的数据、查询空数据 —— 逗号串被迫用 LIKE 的出处
- 🗄️ 数据库基础 · 索引 —— 全课路线图