数据库三大范式详解

文章目录

数据库三大范式

一、范式的定义

  • 设计数据库表时所要遵循的某种规范的级别
  • 比如家里装修买建材,最环保的是E0级,其次是E1级,还有E2级等等
  • 数据库范式也分为1NF,2NF,3NF,BCNF,4NF,5NF,一般在设计关系型数据库的时候,最多考虑到BCNF足够,为了性能上或者应对扩展的需要,达到1NF或者2NF即可
  • 符合高一级范式的设计,必定符合低一级范式,如符合2NF的关系模式,必定符合1NF

二、第一范式 (1NF)

1. 关系和关系模式的概念

  • 关系可以理解为一张带数据的
  • 关系模式是这张数据表的表结构
  • 二者的关系类似于面向对象程序设计中”类“与”对象“的区别,”关系“是”关系模式“的一个实例

2. 第一范式的概念

  • 1NF的定义为:符合1NF的关系中的每个属性都不可再分

    • 通俗的理解为,数据库表的每一列都是不可再分的原子列,如下图所示就不符合1NF的要求

      《数据库三大范式详解》

  • 1NF是所有关系型数据库的最基本要求

    • 也就是说,只要在关系型数据库中已经存在的数据表,一定是符合1NF的,如下图所示就符合1NF的要求

      《数据库三大范式详解》

3. 第一范式存在的问题

以下面这张stu表来说明存在的问题

《数据库三大范式详解》

  • 数据冗余过大

    • 每一名学生的学号、姓名、系名、系主任这些数据重复多次。每个系与对应的系主任的数据也重复多次
  • 插入异常

    • 假如学校新建了一个系,但是暂时还没有招收任何学生,那么添加数据时,会将系名与系主任的数据单独地添加到数据表中,而没有添加学生列的数据,数据添加不合法
  • 删除异常

    • 删除时会将整行的数据删除,假如将某个系中所有学生相关的记录都删除,那么所有系与系主任的数据也就随之消失了(一个系所有学生都没有了,并不表示这个系就没有了)
  • 修改异常

    • 假如李勇转系到法律系,那么为了保证数据库中数据的一致性,需要修改三条记录中系与系主任的数据

三、第二范式 (2NF)

1. 理解几个概念

1.1 函数依赖

  • 类似于函数关系 y = f(x),在x确定的情况下,y一定是确定且唯一的,此时称为y函数依赖于x
  • 对应到数据库中,函数依赖指的是若在一张表中,在属性(或属性组)X的值确定的情况下,必定能确定属性Y的值,那么就可以说Y函数依赖于X,写作 X → Y
  • 对应到上图的stu表中,可以说姓名函数依赖于学号,写作 学号 → 姓名。但是反过来,因为可能出现同名的学生,所以有可能不同的两条学生记录它们在姓名上的值相同,但对应的学号不同,所以不能说学号函数依赖于姓名

1.2 完全函数依赖

  • 写法为 X F→ Y,Y的确定需要依赖于X属性组中的所有值

    《数据库三大范式详解》

  • 对应到上图的stu表中,完全函数依赖如下所示:

    • 学号 F→ 姓名
    • (学号,课名) F→ 分数 (注:因为同一个学号对应的分数不确定,同一个课名对应的分数也不确定)

1.3 部分函数依赖

  • 写法为 X P→ Y,Y的确定需要依赖于X属性组中的某些值

    《数据库三大范式详解》

  • 对应到上图的stu表中,部分函数依赖如下所示:

    • (学号,课名) P→ 姓名

1.4 传递函数依赖

  • 如果X→Y,Y→Z,则称Z传递函数依赖于X,写法为 X T→ Z

    《数据库三大范式详解》

  • 举一个传递函数依赖的例子:

    • 系号→系名,系名→系主任,则系主任 T → 系号

1.5 码

  • 设 K 为某表中的一个属性或属性组,若除 K 之外的所有属性都完全函数依赖于 K,则称 K 为候选码,简称为
    • 通俗的可以理解为,假如当 K 确定的情况下,该表除 K 之外的所有属性的值也就随之确定,那么 K 就是码
  • 一张表中可以有多个码,实际应用中为了方便,通常选择其中的一个码作为主码
  • 对应到上图所示的stu表中,(学号、课名)这个属性组就是码

1.6 主属性

  • 包含在任意一个码中的属性称为主属性
  • 对应到上图所示的stu表中,主属性只有两个,学号课名

1.7 非主属性

  • 不包含在任何一个码中的属性称为非主属性
  • 对应到上图所示的stu表中,除 学号课名 之外,其余的属性都是非主属性

2. 第二范式的概念

  • 2NF在1NF的基础上,消除了非主属性对于码的部分函数依赖

  • 判断是否满足第二范式的步骤如下:

    • 第一步:找出数据表中所有的
    • 第二步:根据第一步所得到的码,找出所有的主属性
    • 第三步:数据表中除去所有的主属性,剩下的均为非主属性
    • 第四步:查看是否存在非主属性对码的部分函数依赖
  • 寻找表中的码的诀窍

    • 假如A是码,那么所有包含了A的属性组,如(A,B)、(A,C)、(A,B,C)等等,都不是码了
    • 原因是作为码的要求里有一个“完全函数依赖”,其他属性仅依赖A就可以确定值了,没必要依赖B或C等,不满足完全函数依赖
  • 对应到上图所示的stu表中,判断过程如下:

    • 第一步,确定了表中的为(学号、课名),且只有这一个码

    • 第二步,确定了主属性为学号课名

    • 第三步,确定了非主属性有四个:姓名系名系主任分数

    • 第四步

      • 对于(学号,课名) → 姓名,有 学号 → 姓名,存在非主属性 姓名 对码(学号,课名)的部分函数依赖

      • 对于(学号,课名) → 系名,有 学号 → 系名,存在非主属性 系名 对码(学号,课名)的部分函数依赖

      • 对于(学号,课名) → 系主任,有 学号 → 系主任,存在非主属性 系主任 对码(学号,课名)的部分函数依赖

    • 所以stu表中存在非主属性对码的部分函数依赖,最高只符合1NF的要求,不符合2NF的要求

3. 1NF转换为2NF的方式

  • 将1NF转换为2NF只有一个办法,就是将大数据表拆分成两个或者更多个更小的数据表,这个过程叫做模式分解

  • 模式分解的方法不是唯一的,对于上图的stu表采用一种模式分解方法如下:

    • 将stu表分成选课表学生表

      • 选课(学号,课名,分数)
      • 学生(学号,姓名,系名,系主任)
    • 选课表和学生表如下图所示:

      《数据库三大范式详解》 《数据库三大范式详解》

  • 判断选课表是否满足2NF的要求

    • 对于选课表,其码是(学号,课名),主属性是学号课名,非主属性是分数
    • 学号确定,并不能唯一确定分数课名确定,也不能唯一确定分数,所以不存在非主属性分数对于码 (学号,课名)的部分函数依赖,所以此表符合2NF的要求
  • 判断学生表是否满足2NF的要求

    • 对于学生表,其码是学号,主属性是学号,非主属性是姓名、系名系主任
    • 因为码只有一个属性,所以不可能存在非主属性对于的部分函数依赖,所以此表符合2NF的要求

4. 第二范式存在的问题

  • 观察改进后满足第二范式的stu表是否还存在第一范式的问题:
    • 李勇转系到法律系
      只需要修改一次李勇对应的系的值即可。——有改进
    • 数据冗余是否减少了?
      学生的姓名、系名与系主任,不再像之前一样重复那么多次了。——有改进
    • 删除某个系中所有的学生记录
      该系的信息仍然全部丢失。——无改进
    • 插入一条暂无学生的新系的记录
      因为学生表的码是学号,不能为空,所以此操作不被允许。——无改进
  • 所以说,仅仅符合2NF的要求,很多情况下还是不够的,而出现问题的原因在于仍然存在非主属性系主任对于学号的传递函数依赖

四、第三范式 (3NF)

1. 第三范式的概念

  • 3NF在2NF的基础之上,消除了非主属性对码的传递函数依赖
    • 通俗的理解为,如果存在非主属性对码的传递函数依赖,则不符合3NF的要求
  • 判断学生表是否符合3NF的要求
    • 对于选课表,主码为(学号,课名),主属性为学号课名,非主属性只有一个,为分数,不可能存在传递函数依赖,所以选课表的设计符合3NF的要求
  • 判断选课表是否符合3NF的要求
    • 对于学生表,主码为学号,主属性为学号,非主属性为姓名系名系主任。因为 学号 → 系名,同时 系名 → 系主任,所以存在非主属性系主任对于码学号的传递函数依赖,所以学生表的设计不符合3NF的要求

2. 2NF转换为3NF的方式

  • 为了让数据表满足3NF的要求,必须进一步进行模式分解为以下形式:

    • 选课(学号,课名,分数)
    • 学生(学号,姓名,系名)
    • 系(系名,系主任)
  • 新的数据库表如下图所示:

    《数据库三大范式详解》 《数据库三大范式详解》 《数据库三大范式详解》

  • 对于选课表,符合3NF的要求,之前已经分析过了

  • 对于学生表,码为学号,主属性为学号,非主属性为系名,不可能存在非主属性对于码的传递函数依赖,所以符合3NF的要求

  • 对于表,码为系名,主属性为系名,非主属性为系主任,不可能存在非主属性对于码的传递函数依赖(至少要有三个属性才可能存在传递函数依赖关系),所以符合3NF的要求

3. 第三范式的优势

  • 判断3NF是否存在2NF存在的问题

    • 删除某个系中所有的学生记录
      该系的信息不会丢失。——有改进
    • 插入一条暂无学生的新系的记录
      因为系表与学生表目前是独立的两张表,所以不影响。——有改进
    • 数据冗余更加少了。——有改进
  • 结论

    • 符合3NF要求的数据库设计,基本上解决了数据冗余过大,插入异常,修改异常,删除异常的问题
    原文作者:Nice2cu_Code
    原文地址: https://blog.csdn.net/weixin_49343190/article/details/117435819
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞