数据库的设计不仅仅是设计的方法的规范决定了这一切,在数据库的实际应用过程中,通过对于现实问题的抽象转换为具体的理念,是对数据库设计的基本的实现。
简单的来说,正规化是在设计表的时间,就是为了消除其冗余性和不协调的从属关系。我将通过一个简单的案例来逐步的说明五大范式在处理数据中的作用和他们的具体的体现。
假设你是一个公司的HR,那么你首先要做的就是知道你招聘的这些人基本的个人信息。那么就做一个简答的统计。被招聘的人的姓名,毕业的学校,学校所在的地址,他们的QQ,微信这些联系方式(在这里,我们只是简单的演示案例,不要去纠结这些数据的完整性和可真实性)
原始的信息表(未做任何书库处理,不符合任何的范式):
PersonInfo表:
姓名 | 毕业院校 | 院校地址 | 微信 | |
张三 | 安阳工学院 | 安阳 | 11451856 | zhangsan123 |
李四 | 郑州大学 | 郑州 | 11548569 | lisi526 |
王五 | 安阳师范学院 | 安阳 | 11154285 | wangwu321 |
我们可以看出这张信息表并没有做任何的正规化处理,我们将这种形式的表称为零状态形式的表。
显然,如果将这样的信息直接输入到数据库,就会出现很多的问题。例如,当张三的QQ被盗了,他重新去申请一个新的QQ,比如,作为HR的你要去增加一个联系的方式(比如你要去增加一个邮箱),那么你就要再次在原先已经做好的信息表中再次多加一列,显然,这不是一个好办法。因为你要做的是一个具有可扩展的系统。这时就要考虑到第一范式的应用。
第一级正规化形式(第一范式)
三点要求:
1.消除每个表格中重复的组
2.为每套相关的数据建立一个独立的表格
3.使用一个主键(primary-key)来标识每套相关的数据
很明显:以上我们最初的信息表很明显的违背了上面我们定义的第一条要求(表中无论是QQ还是微信,都是属于联系方式的一种),那么第三条是是什么意思呢?它其实就是说要在每一条的记录里面去添加一个为的,自动增加的整形值。通过这个值,就可以将两个姓名一样的记录区分开来。通过应用第一级正规化形式,我们得到了以下的表格:
编号 | 姓名 | 毕业院校 | 院校的地址 | 联系方式 |
1 | 张三 | 安阳工学院 | 安阳 | 11451856 |
1 | 张三 | 安阳工学院 | 安阳 | zhangsan123 |
2 | 李四 | 郑州大学 | 郑州 | 11548969 |
2 | 李四 | 郑州大学 | 郑州 | lisi526 |
3 | 王五 | 安阳师范学院 | 安阳 | 11154285 |
3 | 王五 | 安阳师范学院 | 安阳 | wangwu321 |
现在看到的这个表格就是在进行完第一范式处理之后的符合了第一范式的形式了,
它解决的了联系方式(原来的QQ和微信)的限制的问题。
但是第一范式又产生了新的问题:
当我们每一次向PersonInfo表中插入一条数据的时候,你会发现一些数据会重复出现,这样数据库和原来的相比价,数据库比以前更大了,而且很容易出错。
第二级正规化形式 (第二范式)
二点要求:
1.为应用在多条记录的字段建立独立的表格
2.通过一个foreign key来关联这些表格的值
我们将联系方式的值放在一个独立的表格中,这样我们就可以在以后加入更多的数据,而无需担心产生重复的值。我们还通过主键值来关联这些字段:
PersonIonfo 表:
编号 | 姓名 | 毕业院校 | 院校的地址 |
1 | 张三 | 安阳工学院 | 安阳 |
2 | 李四 | 郑州大学 | 郑州 |
3 | 王五 | 安阳师范学院 | 安阳 |
编号 | 联系方式编号 | 联系方式 |
1 | 1 | 11451856 |
1 | 2 | zhangsan123 |
2 | 3 | 11548969 |
2 | 4 | lisi526 |
3 | 5 | 11154285 |
3 | 6 | wangwu321 |
如上所示,我们创建了独立的表格,PersonInfo表中的主键编号现在与ContactInfo表中的foreign key 联系方式编号关联。现在的情况好象已经得到了明显的改善。不过,如果我们要为数据库加入一个人的记录呢?或者更多,一千个甚至一万个?这样我们就必须重复使用毕业学校和院校的地址,这明显冗余。因此我们将应用第三级正规化方法。
第三级规范形式(第三范式)
1:消除不依赖的字段
所谓的传值依赖,就是主键,非主键1,非主键2,这三者之间不能出现传递的依赖关系,如果你可以由主键推出非主键1,然后由非主键1推出非主键2,这时间非主键2就产生了传值依赖的关系,这样就不满足三范式了。
也就是说,在一个表的,当然以一条记录为单位,主键和非主键之间可以产生父子关系,但是在非主键之间是不能出现父子关系的。
推理:编号1------->毕业院校(安阳工学院), 毕业院校(安阳工学院)--------->院校的地址
解释:编号1(也就是张三这个人),,当你知道他的编号,你想,这个人的毕业院校是唯一的,大学的地址也是唯一的(不要考虑人家转学或者大学地址搬迁了,你这不是抬扛吗?)所以,这样的逻辑在表中是严格的不被允许的。
那么我们就要考虑把这一部分的数据继续抽取出来,作为一个单独的表的进行处理。
PersonIonfo 表:
编号 | 姓名 | 院校编号 |
1 | 张三 | 1 |
2 | 李四 | 2 |
3 | 王五 | 3 |
University表:
院校编号 | 毕业院校 | 院校的地址 |
1 | 安阳工学院 | 安阳 |
2 | 郑州大学 | 郑州 |
3 | 安阳师范学院 | 安阳 |
编号 | 联系方式编号 | 联系方式 |
1 | 1 | 11451856 |
1 | 2 | zhangsan123 |
2 | 3 | 11548969 |
2 | 4 | lisi526 |
3 | 5 | 11154285 |
3 | 6 | wangwu321 |
这样我们就将university表中的主键院校编号和Person表中名字为院校编号的foreign key关联起来,就算为ABC公司加入200个员工,在university表中也只有一条记录。我们的PersonInfo表和contactionInfo表可以不断地扩大,而无需担心插入不必要的数据。实际上大多数的数据库设计到满足第三范式就可以了,它已经基本满足了所以的要求,但是我们还是可以继续进行更深一步的数据优话化。
关于如何采用第四范式的优化,将在下一篇的博文中进行详细的说明和解释。本文将不再进行讲解。
本篇文章属于博主自己原创,博主能力有限,菜鸟一枚,如果发现问题,请各位大神多多指教。