第一范式:表中所有列不能被分解为更基本的数据单位(原子性)。
第二范式:满足第一范式的前提下,表中所有非主属性,都依赖且必须依赖所有的主属性(非主键字段与主键字段间的关联性)。
第三范式:满足第一范式的前提下,表中所有非主属性,不能互相间有依赖(非主键字段间的非关联性)。
下面详细解释一下每个范式的含义:
第一范式:字段的原子性。
原子性顾名思义代表的是不可拆分。诸如一个人的年纪、手机号、性别,这样的属性都是不可拆分的。诸如家庭地址,“某某省某某市某某街道”,可以根据业务需求,如果需要分别区分不同的省市街道,那么则是可拆分的。如果不需要区分省市街道,那么这样的数据也可以作为不可拆分的。
姓名、年纪、性别 |
张三、13、男 |
表中的每一列都要求是不能被继续拆分的数据,如上图中“张三,13,男”这样的数据必须要被拆分成如下图三个字段“张三”、“13”、“男”。
姓名 | 年纪 | 性别 |
张三 | 13 | 男 |
同时还要考虑实际业务的需求,有时候地址可以作为一个字段填写,如“XX省XX市XX街道”,但有时候需要按省市以及详细地址来分成几个字段来填写,如“XX省”、“XX市”、“XX街道”。
第二范式:非主键字段与主键字段的关联性。
这里的关联性通常是我们制定的数据间的关联性。如给每一个用户指定一个用户ID,那么用户ID与用户数据间就存在一个关联性。也如给每一个角色指定一个角色ID,那么角色ID与角色数据间也存在一个关联系。同时我们再给每一个用户的ID分配对应的角色ID,此时的关联性是存在于用户ID与角色ID间。但是用户数据与角色数据间是不存在任何的关联性。
在针对于联合主键的时,关联性要求所有的非主键字段必须与主键字段中的每一列都有关联性。
举个例子如user表中有字段id,name,age,email,telephone。这里的主键字段是id,其他的字段都是与id关联。
如果还有一个表用来记录用户角色,字段有role_id(角色id)、user_id(用户id)、role_type、user_name、user_age等。这里的主键不论是定义role_id(会有user_name、user_age与它没有必然的关联),还是定义user_id(会有role_type与它没有必然的关联),或者是定义role_id和user_id(role_type仍是只与role_id有关联,而不与role_id和user_id有关联,第二范式针对联合主键时要求非主键字段必须和主键中的每一个字段都有关联)。这些都是违反了第二范式,因此必须要将role_type和user_*的字段分别存放在不同的设计表中。
第三范式:非主键字段间的非关联性。
一个表中只能有一个主键,我们假设是A,同时还有其他的两个字段B和C。那么他们中存在的关系只能是B→A和C→A,而不能存在C→B或B→C。
同样以用户角色表来举例,字段有role_id(角色id)、user_id(用户id)、role_type、user_name、user_age等。在这里假设以role_id作为主键,那么user_name实际是与user_id有关联关系,user_id与role_id有关联关系,等价于C→B→A。这样的结构也是不符合第三范式。