⚠️ Alpha内测版本警告:此为早期内部构建版本,尚不完整且可能存在错误,欢迎大家提Issue反馈问题或建议
Skip to content

4.1.3 数据表的设计规则——范式理论:1NF/2NF/3NF 规范化过程

一句话破题

范式是数据库设计的"卫生标准"——遵守它能避免数据冗余和更新异常。

为什么需要范式?

不规范的表设计会带来三大问题

问题说明示例
数据冗余相同信息重复存储每条订单都存储完整的客户地址
更新异常修改数据需要改多处客户改地址,要更新所有相关订单
删除异常删数据可能丢失有用信息删除唯一订单时,客户信息也没了

三大范式速览

范式核心要求通俗解释
1NF字段不可再分一个格子只放一个值
2NF非主键完全依赖主键所有字段都跟主键直接相关
3NF消除传递依赖字段之间不要"套娃"依赖

第一范式:原子性

规则:每个字段的值必须是不可再分的原子值。

反例

订单ID商品列表
001苹果,香蕉,橙子

正确做法

订单ID商品
001苹果
001香蕉
001橙子

或者使用关联表:

prisma
model Order {
  id    String      @id
  items OrderItem[]
}

model OrderItem {
  id       String @id
  orderId  String
  product  String
  quantity Int
  order    Order  @relation(fields: [orderId], references: [id])
}

第二范式:完全依赖

规则:非主键字段必须完全依赖于主键,不能只依赖主键的一部分。

反例(复合主键场景):

学生ID课程ID学生姓名课程名称成绩
S001C001张三数学90

问题:学生姓名只依赖学生ID课程名称只依赖课程ID

正确做法:拆分成三张表

prisma
model Student {
  id      String   @id
  name    String
  scores  Score[]
}

model Course {
  id      String   @id
  name    String
  scores  Score[]
}

model Score {
  studentId String
  courseId  String
  score     Int
  student   Student @relation(fields: [studentId], references: [id])
  course    Course  @relation(fields: [courseId], references: [id])
  
  @@id([studentId, courseId])
}

第三范式:消除传递依赖

规则:非主键字段不能依赖于其他非主键字段。

反例

员工ID员工姓名部门ID部门名称部门地址
E001张三D001技术部3楼

问题:部门名称部门地址依赖于部门ID,而不是直接依赖于员工ID

正确做法

prisma
model Employee {
  id           String     @id
  name         String
  departmentId String
  department   Department @relation(fields: [departmentId], references: [id])
}

model Department {
  id        String     @id
  name      String
  location  String
  employees Employee[]
}

规范化的实际效果

规范化前:订单表存储冗余客户信息

订单表:
| 订单ID | 客户ID | 客户姓名 | 客户地址 | 商品 | 金额 |

规范化后

prisma
model Order {
  id         String   @id
  customerId String
  customer   Customer @relation(fields: [customerId], references: [id])
  items      OrderItem[]
  total      Decimal
}

model Customer {
  id      String  @id
  name    String
  address String
  orders  Order[]
}

范式检查清单

设计表时,逐项检查:

  • [ ] 1NF:所有字段都是原子值?没有数组或逗号分隔的值?
  • [ ] 2NF:所有非主键字段都依赖于完整的主键?
  • [ ] 3NF:非主键字段之间没有依赖关系?

实际开发中的权衡

范式理论是理想状态,实际开发中需要权衡:

严格遵守范式适度违反范式
数据一致性好查询性能更高
存储空间小减少 JOIN 操作
更新方便代码更简单

建议:先按范式设计,遇到性能瓶颈再考虑反范式化(下一节详述)。

本节小结

  • 1NF:字段值不可再分
  • 2NF:非主键完全依赖主键
  • 3NF:消除传递依赖
  • 遵守范式能避免数据冗余和更新异常
  • 实际开发中需要在规范和性能之间权衡