关于关系型数据库表的设计

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/pp634077956/article/details/54578061

这篇文章主要是总结一下看书的收获,至于具体的实例,可能等到以后工作了才能给出吧,最近没遇到什么数据库的问题。

表的设计最基本的就是要满足一些范式,所谓范式,可以理解为对设计标准的满足程度。我暂时只学习了三个范式。

[0]:第一范式:

一张表必须要使得每一列都满足原子性才能满足第一范式(其实还必须有主键,但是这个太基本了)。什么叫做原子性,个人认为可以理解成一个属性还能不能继续分割的程度。而原子性在表中又体现在两个方面,第一是一个列不能含有多个同类的值,比如这种列(interest:’music,football,tennis,hiking,math’)。第二是不能有多个表示同一类型属性的列。比如interst1,interst2..这种。

why not?

第一,这非常不方便查询,假设我们需要对interst这个列进行查询,你就必须写很多代码来处理这一长串的字符,因为这些爱好都混杂在一起了。

其次,多个类似的列会造成设计和查询困难以及数据冗余。比如interst1,interst2其实都是代表interst的一部分,但是现在我们要找一个具有’music’爱好的人,这查询就必须判断music是不是在这四个interst里面,这就相对比较麻烦了。如果要找’muisc’和’culture’就更加困难了。还有,并不是每一个人的爱好都是一样的,这样势必导致我们要按照爱好最多的那个来设置列数,这就会导致很多列都是空的。

解决办法是什么呢?就是将这样的列存储到另外的一个表里面去!你会发现这个做法一下就解决了我们前面的搞来搞去都无法保证原子性的问题。另外一个表的格式可以是(people_id,interest).这里的interst只代表某一个具体的爱好。例如(1,’maht’),(1,’hiking’)….这样这两个元素共同构成主键。当然,保证原子性有很多方式,比如我们可以将一个adress分割成为street,room number,city也是保证原子性,这个比interst好处理多了。

note:我们并不是一味的追求原子性,不同的需求对原子性的要求也是不一样的。主要看你的需求要求分割到什么层次。

[1]第二范式:

如果一个列X的值可以决定列Y的值,我们就叫X->Y:Y依赖于X.如果一张表存在多余一个的码(组合主键),而且存在一个码的真子集U使得U->V,V是不是码的子集,我们就说它不满足第二范式(存在部分依赖)。

上面这段话是不是看着不太像人话?

~^_^~

其实通俗来讲,我认为可以这样理解,首先码肯定是决定了整个元组的值的,所以任何一个非主键都一定依赖于码,这个是必然的,没什么讨论的价值。我们关注的是:如果一个非主键可以被码的一部分决定,那么说明存在部分依赖,这时候存在一个什么样的问题呢?

注意了,这代表这些列依赖往往会造成信息的重复以及低耦合性。举出一个例子(课程名,学号,分数,姓名,系名,系主任)。假设学号和课程是主键,那么显然姓名依赖于学号,(系名,系主任)依赖于学号.这样我们就可以发现,很多信息是重复出现了的,比如系名,系主任,姓名,而且这些属性都是可以继续分割成更合理的实体的。所以我们可以把造成干扰的移走,只留下分数,这个不依赖于任何主键的真子集!然后剩下的属性只依赖于学号,所以正确的做法显然就是把这些存储在一个以学号为主键的表即可,由于只有一个主键,显然不存在部分依赖,也不存在什么信息重复:(学号,姓名,系,系主任)。

第三范式,通俗的讲就是满足第二范式的前提下,某一个非主键A依赖于另外一个非主键B,而B依赖于某一个主键C.

这造成什么问题呢?最明显的问题就是信息的高耦合。就像你硬生生的把系的信息和学生的信息整合在一起,这逻辑上就很别扭,而且不方便我们单独查找有关于学生或者系的信息(数据表会比较大,影响查找速度,第二是其他的表想要使用单独的系的信息就不方便了)。所以我们需要继续拆分,比如将系和系名这个信息拆分出去,原来的表里面只需要留一个系名就可以了。这样我们就又渐少了一点信息的冗余,并且使得表的耦合降低。

说到这里,我们有必要回头看一下我们在[0]部分拆分出来的一个表(people_id,interest),由于这里只有一个码,没有非主键,所以肯定是不存在依赖的,但是我们还是可以发现,interst似乎变成一个单独的表会更加合适一点,因为它是一个多对多的关系。可以变成(people_id,interst_id),(interest_id,interest),这里我们拆分成了多对多的关系有几个好处,第一确保没有数据的低耦合,显然最开始interest必须要依赖于people_id而存在,如果我们要单独研究interest的时候就比较麻烦了。同时如果我们删除某一些people_id可能导致某一种interest不存在了,这从逻辑上就讲不通,这就可能造成删除异常。最后如果我们需要对interst使用join的时候,对比字符串和对比id显然后者的效率要高的多。

最后我想从两个方面来总结设计的原则:

[0]:信息的重复:重复导致冗余,重复导致修改异常麻烦。

[1]:信息的耦合,信息高耦合导致表难以复用或者高效的复用,导致插入时候必须连带插入其他的无关信息。也导致删除的异常。

无论是三大范式还是多对多,一对多等设计模式,都是在解决这两个大的方面。最后,也是最重要的一条原则:多从查询出发,从需求出发!

猜你喜欢

转载自blog.csdn.net/pp634077956/article/details/54578061