关系型数据库设计
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_id
, vet_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 比较复杂,暂时先挂起吧!