UP | HOME

关系型数据库设计

Table of Contents

1 好的数据库设计原则

1.1 原则 1 没有冗余

  • 除了外键以外,数据库中的每个域 (field) 仅仅存在一张表 (table) 中
  • 外键 (primary key) 的重复是允许的,因为数据库表之间需要通过外键来连接

1.2 原则 2 没有 “坏的” 依赖

在数据库的所有表中,所有数据仅仅取决于主键,不能有: 部分依赖 (partial dependencies) 或 传递依赖 (transitive dependencies)。

数据库在设计时根据其 “坏的” 依赖程度不同被分成了不同的正规化 (normalization), 并根据不同正规化总结了 6 中范式 (normal forms)。

简记 全称
1NF First Normal Form
2NF Second Normal Form
3NF Third Normal Form
BCNF Boyce-Codd Normal Form
4NF Fourth Normal Form
5NF Fifth Normal Form

范式在上表由上自下是包含关系,即符合 2NF 的数据库必然符合 1NF 。

2 1NF

1NF 要求数据库每个表的每一列都是 原子的 ,即表中的每一列不能拆分成更细的数 据项。

clients 表记录了顾客和兽医以及宠物的数据,例如:

client_id client_name vet_id vet_name pet_id pet_name pet_type
2122 Jack 21 PetVet 1, 2, 3 Sam, Hoober, Tom Bird, Dog, Hamster
2428 James 21 PetVet 1 Tim Dog
2317 Vernon 45 PetCare 2 Charlie Cat
8324 Helen 95 PetXY 1, 2 Kirby, Beefer Dog, Cat
+-- clients -------------+
|                        |
| client_id: primary key |
| client_name            |
| vet_id                 |
| vet_name               |
| +-- pets --------+     |
| |                |     |
| | pet_id         |     |
| | pet_name       |     |
| | pet_type       |     |
| +----------------+     |
+------------------------+

在表中的有的顾客可能给一个兽医不止一个宠物,这会导致数据不原子的。为了消除这样 的问题,可以添加外键引用,结果如下:

     +-- clients -------------+
  1  |                        |
+--->+ client_id: primary key |
|    | client_name            |
|    | vet_id                 |
|    | vet_name               |
|    +------------------------+
|
|    +-- pets ----------------+
|    |                        |
|    | pet_id                 |
|    | pet_name               |
|    | pet_type               |
+----+ client_id: foreign key |
  *  +------------------------+

3 2NF

部分依赖关系是指某个属性只由构成主键的部分列决定,而和另一些列无关。例如对课程表

+-- courses -------------------------+
|                                    |
| course_id                          |
| student_no                         |
| student_name                       |
| score                              |
| primary key(course_id, student_no) |
+------------------------------------+

此表的主键是(学号,课程号),而“姓名”列只由“学号”决定,与“课程号”无关,这就是 部分依赖关系。2NF 在满足 1NF 时还要求不包含部分依赖。

4 3NF

传递依赖是当一个非码的属性 A 依赖于另一个非码属性 B,但 B 并不能用作表的主键。

+-- clients -------------+
|                        |
| client_id: primary key |
| client_name            |
| vet_id                 |
| vet_name               |
+------------------------+

在上面的 clients 表中 vet_name 依赖于 vet_idvet_id 又依赖于 client_id ,所以 vet_name 传递依赖于 client_id

     +-- clients -------------+             +-- vets ----------------+
  1  |                        |          1  |                        |
+--->+ client_id: primary key |      +----->| vet_id: primary key    |
|    | client_name            |      |      | vet_name               |
|    | vet_id: foreign key    +------+      +------------------------+
|    +------------------------+  *
|
|    +-- pets ----------------+
|    |                        |
|    | pet_id                 |
|    | pet_name               |
|    | pet_type               |
+----+ client_id: foreign key |
  *  +------------------------+

通过上述的表拆分,将 clients 添加 vet_id 外键来消除传递依赖。

5 BCNF, 4NF, 5NF

通常创建数据库是满足 3NF 就可以了,BCNF, 4NF, 5NF 比较复杂,暂时先挂起吧!

Last Updated 2020-02-22 Sat 20:06. Created by Jinghui Hu at 2019-06-28 Fri 11:04.