数据库三范式

2,277 阅读4分钟

1NF

  • 每个属性都不可再分。即每个列不可再分。 1NF是所有关系型数据库的最基本要求。
    71900-0hxmegxcav4i.png

2NF

  • 2NF在1NF的基础之上,消除了非主属性对于码的部分函数依赖。 出现的概念:非主属性,码,部分函数依赖。

函数依赖

  • 简单来说,就是通过x可以唯一的确定y,比如身份证号可以唯一的确定人名。 那么,就称x函数确定yy函数依赖于x。记作 x→y
  • x称为这个函数依赖的决定属性组,也称为决定因素。
  • 若 x→y,y→x,则记作 x←→y。 若y函数不依赖于x,则记作
    30594-6szm5vjrpmr.png

平凡函数依赖于非平凡函数依赖

  • 若 x→y ,但y不是x的子集,则称 x→y 是非平凡的函数依赖。 若 x→y ,但yx的子集,则称 x→y 是平凡的函数依赖。

  • 例子,以学生学号sno,课程编号cno,学生课程成绩grade为例。

    • 非平凡函数依赖:(sno, cno) → grade
    • 平凡函数依赖:(sno, cno) → sno ;  (sno, cno) → cno 。

完全函数依赖与部分函数依赖

完全函数依赖
  • 若 x → y,且 x 的任何一个真子集 x',都不可能 x' → y,则称 y 对 x 完全函数依赖。 记作
    43467-2nkh3lzxudw.png
  • 比如通过学生学号sno,课程编号cno可以确定学生该课程的成绩grade。 但无法从(sno, cno)的任何真子集中如sno确定学生某一课程的成绩。则称grade对(sno, cno)完全函数依赖。
部分函数依赖
  • 若 x → y,但 y 不完全函数依赖于 x,则称 y 对 x 部分函数依赖。 记作
    37159-9yhqdmuwbcq.png
  • 比如身份证号码id和手机号码phone可以确定姓名name。 但存在存在 id → name,即部分函数依赖。

传递函数依赖与直接依赖

传递函数依赖
  • 若 x → y,y → z。(y 不是 x 的子集,且不存在 y → x)
  • 如学号sno → 系名dept_name, 系名dept_name → 系主任dept_manager_name。 且dept_name 不是 → sno,不是sno的子集。所以dept_manager_name传递函数依赖于sno
直接依赖
  • 若 x → y,y → z。且 y → x,即 y ←→ x。 则 z 直接依赖为 x。

  • 94875-7l5cc08ccai.png
    则称k为候选码(Candidate Key)。若候选码多于一个,则选定其中一个作为主码(Primary Key,主键)。
  • 如身份证号码id、学号sno都能确定学生的姓名sname,如下表。 那么idsno为码。若选择id为主键,即主码。
id sno sname

主属性与非主属性

  • 包含在任何一个候选码中的属性,称为主属性。 不包含在任何码中的属性称为非主属性。
  • 如下表。显然(cno, sno)为主码,即 cno、sno 为主属性。 而 grade 为非主属性。
cno(课程号) sno(学号) grade(学生课程成绩)

全码

  • 整个属性组是码,称为全码(All-key)

外码

  • 即外键

2NF

  • 回到定义上来:2NF在1NF的基础之上,消除了非主属性对于码的部分函数依赖。
  • 首先想想主属性对于码的函数依赖是什么,如(a,b)是主键,那a部分函数依赖于(a,b)。这种关系不用消除。

例子

  • 非主属性对于码的部分函数依赖,如下表。sdept 可以通过 sno 来确定,且 sdept 是非主属性,这就叫存在非主属性的部分函数依赖。 这种关系很明显会导致数据冗余。如一个学生选了多门课程,每门课程都对应一行记录,每行记录都要去存储重复的sdept
cno(课程号) sno(学号) grade(学生课程成绩) sdept(学生系名)
  • 2NF就是消除下图中的虚线。
    54621-wrcc0zqi8xn.png

符合2NF的设计

cno(课程号) sno(学号) grade(学生课程成绩)

sno(学号) sdept(学生系名)

3NF

  • 3NF在2NF的基础上,消除了非主属性对于码的传递函数依赖。

例子

  • 如下表,sno是码,sno → sdept,sdept → sloc,且符合传递依赖的定义,所以 sloc 传递依赖于 sno。
  • 这种情况,同样会造成数据的大量冗余,由于同一个系的学生的地址是一样的。
sno(学号) sdept(学生系名) sloc(学生宿舍地址,同一个系的学生一个地址)

35734-3uvwrtuwnjp.png

符合3NF的设计

sno(学号) sdept(学生系名)

sdept(学生系名) sloc(学生宿舍地址,同一个系的学生一个地址)