← 返回文章列表
数据库·927 次阅读

数据库设计:三大范式与主外键

数据库设计:三大范式与主外键

函数依赖

理解范式的前提。如果知道 A 的值就能确定 B 的值,就说 B 依赖于 A。知道学号就能确定姓名 → 姓名依赖学号。主键能确定整行所有字段。

三大范式(逐级递进)

第一范式 1NF:字段不可再分

每个单元格只存一个原子值。"联系方式"列同时放手机和邮箱就违反 1NF,应拆成两列。标签如果以逗号字符串存在一个字段里,查询和维护都困难(是否拆分取决于业务,标签系统常用关联表)。

第二范式 2NF:在 1NF 基础上消除部分依赖

针对联合主键——非主键字段必须依赖整个主键,不能只依赖其中一部分。

经典的"学生选课"表 (学号, 课程号) 为主键,但"课程名"只依赖课程号,就应拆出课程表:

选课表(学号, 课程号, 成绩)
课程表(课程号, 课程名)
学生表(学号, 姓名)

第三范式 3NF:在 2NF 基础上消除传递依赖

非主键字段不能依赖另一个非主键字段。订单表里出现"商品分类名",而分类名依赖商品、商品依赖订单主键 → 传递依赖,拆出商品表、分类表。

主键与外键

  • 主键 PRIMARY KEY:唯一标识一行,非空不重复。推荐用与业务无关的自增 id(或雪花算法/UUID,考虑分布式和索引特性)
  • 外键 FOREIGN KEY:引用另一张表的主键,保证引用完整性——不能引用不存在的商品;删除被引用的行会被阻止(级联策略 RESTRICT/CASCADE/SET NULL 按需选)
CREATE TABLE posts (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  category_id INTEGER,
  FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE SET NULL
);

范式的目的与反范式

范式解决三个异常:插入异常(缺信息无法插入)、更新异常(冗余数据改不全)、删除异常(删数据连带丢失有用信息)。

但范式不是越高越好——拆表越多 JOIN 越多。为了查询性能,实际项目常故意反范式:冗余一些字段(如订单快照里的商品名,下单时的价格必须固化),用空间换时间、用历史快照保真实。

设计心法:先按范式设计出逻辑模型,再根据查询模式和性能要求做受控的冗余,并明确冗余字段的同步策略。

看到这里了?如果这篇文章帮到过你

请我喝瓶可乐就好 🥤

收款码

评论0 条

还没有评论,来抢沙发~

发表评论

评论需审核后显示

© 2026 许冬博客 · 专注 JS 技术分享

·RSS 订阅·Powered by Nuxt 4