第一范式(1NF)
定义:数据库表的每一列都是不可分割的原子数据项,而不能是集合,数组,记录等非原子数据项。如果实体中的某个属性有多个值时,必须拆分为不同的属性。
说明:E-R模型允许实体集和联系集具有某些程度的子结构,比如多值属性(一个教师有多个电话号码)、组合属性(包含多个子属性,比如地址包含城市和街道等)。我们在将E-R模型转换成表时,对于这些子结构的一般处理规则是:多值属性用多个元组来存储;组合属性中的每个子属性作为单独的属性,也就是表中的单独列。这个一般处理规则其实也是在满足第一范式的约束。
举例:设计如下Instructor1这张表来存储大学教师信息,每位教师包括教师ID、名字、身份证ID,身份证过期时间、家庭地址、配偶名字、配偶单位这些信息,教师ID是这张表的主键。
Instructor1
ID | Name | Card | Card_Date | Adress | Partner_Name | Partner_Comp |
1023 | Jack | 231322**12 | 08.23.2033 | Beijing Wenhua road | Lina | Baidu |
问题:上面这张表并不满足第一范式,因为Adress这个属性其实包含了城市和街道两个子属性,应该拆分成独立的属性。将其改进后满足第一范式:
Instructor2
ID | Name | Card | Card_Date | City | Street | Partner_Name | Partner_Comp |
1023 | Jack | 231322**12 | 08.23.2033 | Beijing | Wenhua road | Lina | Baidu |
第二范式(2NF)
定义:满足第一范式前提,第二范式(2NF)要求实体的所有非主键属性完全依赖于每一个候选主键。所以只有当存在多个主键的时候,才会发生不符合第二范式的情况。比如有两个候选主键时,不能存在这样的属性,它只依赖于其中一个主键,这就是不符合第二范式。
举例:Instructor2虽然满足第一范式,但是并不满足第二范式,因为教师ID和身份证ID都是候选主键,但是身份证过期时间这个属性只依赖于身份证ID这个属性,为满足第二范式应该将教师身份证信息应该用单独的表来保存。
Instructor3
ID | Name | Card | City | Street | Partner_Name | Partner_Comp |
1023 | Jack | 231322*12 | Beijing | Wenhua road | Lina | Baidu |
Card1
Card | Card_Date |
231322**12 | 08.23.2033 |
第三范式(3NF)
定义:满足第二范式前提,属性不能传递依赖于主键属性。如果某一属性依赖于其他非主键属性,而其他非主键属性又依赖于主键,那么这个属性就是间接依赖于主键,这被称作传递依赖于主键属性,即不满足第三范式。
举例:Instructor3虽然满足第二范式,但是因为配偶单位(Partner_Comp)这个属性依赖于配偶名字(Partner_name)属性,配偶名字属性又依赖于主键属性教师ID,即配偶单位属性传递依赖于主键教师ID,所以不满足第三范式。改进后的版本满足第三范式:
Instructor4
ID | Name | Card | City | Street |
1023 | Jack | 231322*12 | Beijing | Wenhua road |
Partner1
ID | Partner_Name | Partner_Comp |
1023 | Lina | Baidu |
Card1
Card | Card_Date |
231322**12 | 08.23.2033 |
数据库关系(表)设计一般需要满足第三范式。另一方面,这三大范式只是一般设计数据库的基本理念,可以建立冗余较小、结构合理的数据库。如果有特殊情况,当然要特殊对待,数据库设计最重要的是看需求跟性能,需求>性能>表结构。所以不能一味的去追求范式建立数据库。