深入浅出:数据库设计的三大范式及实用经验解析

118 阅读4分钟

今天我们来学习一下数据库的三大范式,范式可以简单理解成标准,可以帮助我们更好的设计数据库。

  1. 第一范式:字段不可再分
  • 举例
    • 我们要存储体检者的双眼视力
    • 那么应该存为左眼视力和右眼视力两个字段
    • 即user表里应该有left_eye和right_eye,而不能把它们存在一个字段
  1. 第一范式的缺点
  • 下图满足了第一范式,但是存在如下问题:
    • 数据冗余
    • 创建系时插入异常
    • 删除学生会导致系消失
    • 学生转系时改动多处

  1. 第二范式2NF
  • 定义
    • 在1NF的基础上,要有键
    • 所有字段分别完全依赖于键
    • 如果键是多个字段组合,则不允许部分依赖于该键
  • 依赖关系
    • 给出键,就能唯一确定字段的值
    • 如给出学号,就能唯一确定姓名,反之则不行,这种情况就称姓名依赖于学号
  • 上图中不满足第二范式的地方
    • 上表的键为(学号,课名)
    • 但存在部分依赖:姓名依赖于学号
  • 将上图根据第二范式进行改变
    • 选课表(学号、课名、分数),键是学号和课名
    • 学生表(学号、姓名、系名、系主任),键是学号

  1. 第三范式3NF
  • 定义: 一个表里不能有依赖传递。
    • 上图选课表中,给出学号,就能确定系名:系名依赖于学号
    • 给出系名,就能确定系主任:系主任依赖于系名,所以,系主任间接依赖于学号,也就是依赖传递
  • 解决办法
    • 把系名和系主任单独建表
    • 最后得到如下图

  • 除此之外还有一个BC范式: 键中的属性也不存在间接依赖
  1. 数据库设计经验
  • 高内聚
    • 把相关的字段放到一起,不相关的分开建表
    • 如果两个字段能够单独建表,那就单独建表
  • 低耦合
    • 如果两个表之间有弱关系
    • 一对一可放在一个表,也可两个表加外键
    • 一对多一般用外键
    • 多对多一般建中间表
  1. 一对一关系举例
  • 假设一个学生只能加入一个班级
    • 可以把班级放在学生表里
    • 学生id:1001姓名:小明班级id:4002
    • 班级id:4002名称:入门1班
  • 也可以单独建立关联表
    • 学生id:1001姓名:小明
    • 学生班级:id:2003学生id:1001班级id:4002
    • 班级id:4002名称:入门1班
  1. 一对多关系举例
  • 假设一个作者能写多本书
    • 可以把书放在作者表里吗?
    • 某些DBMS支持数组,可以存两个id到一个字段
    • 作者id:1001,姓名:大牛,books:[2001,3002]
    • 如果不支持数组,就不能这样做了
  • 单独建立关系表(推荐)
    • 作者id:1001姓名:大牛
    • 出版:id:2001作者id:1001书id:4002,出版社id
    • 出版:id:2001作者id:1001书id:4003,出版社id
    • 书id:4002名称:JS入门
  1. 多对多关系举例
  • 假设一个学生可以加入多个班级,当然每个班级也能有多个学生
  • 可以把班级放在学生表里吗?
    • 某些DBMS支持数组就可以放
    • 如果不支持数组,就不能放了
  • 单独建立关系表(推荐)
    • 学生id:1001姓名:小明
    • 学生班级:id:2001学生id:1001班级id:4002,有效期
    • 学生班级:id:2002学生id:1001班级id:4003,有效期
    • 班级id:4002名称:入门1班
  1. 什么时候建关联表
  • 当关联自身存在属性时
    • 比如关联的有效期,有效期为一年
    • 比如关联的级别,店铺会员分为vip1~6