Office中国论坛/Access中国论坛

标题: 浅谈范式 [打印本页]

作者: roych    时间: 2015-7-18 11:55
标题: 浅谈范式
本帖最后由 roych 于 2015-7-18 12:12 编辑

       并非崇洋媚外,但对比国外,国内不少Access书籍关于范式的讲解真的是泛泛而谈,一页甚至几百字就讲完了。以至于很多新手,包括我在内,开始时都没想过,觉得似乎这查询不好做,代码总可以吧?论坛不是有很多高手么?上论坛问下呗。

       所以每每看到设计比较糟糕的表,总会有股莫明火却无法发作,不能怪版友,毕竟人家是新手,但是这又偏偏层出无穷,只能默默怪某些人急功近利,误人子弟了。于是,便有一种想法,试图把这些整理下,供新手们参考。
       我们还是回到主题上来。

       什么是范式?范式就是数据表规范化的指导思想,其等级按1~5编号,称为第一范式至第五范式(1NF~5NF)。不过一般数据库设计符合第三范式就够了。

       第一范式(列不可分):删除重复组

       当规范化到第一范式时,从表中删除重复字段(又称重复组),由于仍需获取和报告数据,因此终止为相关数据的每个表创建单独的表。其操作如下:
1.        删除单个表中重复的组
2.        为每个集合中相关数据创建单独的表
3.        使用主键识别每个集合中的相关数据
       避免在单个表使用多个字段(重复值)存储相同的数据。最常见表设计是这样的:
宝贝A7月9日7月10日7月11日7月12日
销量3200289031073520
转化率5.30%4.50%4.90%6.20%
      不少从Excel转向Access学习的用户,开始时可能会这样设计表,因为看起来直观。但问题在于数据库部署之后,修改表(例如增加一天的数据)会影响前台跟后台,且需要耗费程序员大量精力和时间(总要写代码,动态去修改字段吧?)。

       替代方法是为销量和转化率创建单独的数据表,存储每天的数据,再以某个字段建立连接。如下所示:
宝贝名称日期销量转化率
宝贝A7月9日32005.30%
宝贝A7月10日28904.50%
宝贝A7月11日31074.90%
宝贝A7月12日35206.32%

作者: roych    时间: 2015-7-18 12:09
本帖最后由 roych 于 2015-7-18 14:31 编辑

       第二范式(表独立):删除重复数据

       第二范式是建立在第一范式的基础之上,且继续删除赋值或重复的数据,将适用于某个表的许多行数据的子集放在单独的表,且创建这些表之间的关联。其操作如下:
1.        满足第一范式的全部要求
2.        将适用于多条记录的值放在单独的表中
3.        使用外键约束创建这些表之间的关联
       我们还是拿上面的例子来说事。假定我们增加一个SKU,于是就成了这样一个表:
SKU宝贝名称日期销量转化率
123宝贝A7月9日32005.30%
123宝贝A7月10日28904.50%
123宝贝A7月11日31074.90%
       我们依葫芦画瓢。第一条,检查后显然是符合的;第二条,显然,SKU跟宝贝名称是“适用于多条记录的值”,所以我们可以建立一个宝贝信息表:
SKU宝贝名称
123宝贝A
       把这这两个字段独立出来之后,显然得想办法把宝贝A与销量建立起联系。也就是第三条。这时候,我们可以考虑使用SKU作为销量表的外键,于是,原表改为:
IDSKU日期销量转化率
11237月9日32005.30%
21237月10日28904.50%
31237月11日31074.90%
SKU连接后即可获取宝贝A的销量和转化率。

作者: roych    时间: 2015-7-18 12:09
本帖最后由 roych 于 2015-7-18 15:42 编辑

第三范式(主键独立):删除不依赖于主键的字段
       第三范式是建立在第二范式的基础之上,能带来大多数数据库解决方案的规范化水平。当表中的字段不依赖于该表的主键时,第三范式将删除该表中的这些字段。其操作如下:
1.        满足第二范式的全部要求
2.        删除不依赖于该表主键的字段
3.        将这些字段放在一个表或者多个表中。
       我们再来看看上面的表,销量并不是依赖于SKU(而是订单号)而存在,因此如果有订单信息表的话,销量字段是不必创建的。于是上面的表最终可以拆分为三个表:
       宝贝信息表:
SKU宝贝名称
123宝贝A
       流量表:
IDSKU日期转化率
11237月9日5.30%
21237月10日4.50%
31237月11日4.90%
       订单明细表:
订单号SKU日期订购数量
88881237月9日100
88891237月9日150
……………………
这就是完整的第三范式。

作者: roych    时间: 2015-7-18 12:19
本帖最后由 roych 于 2015-7-18 12:38 编辑

       最后再讲讲主键的考虑前提:
1、  它在整个数据库中是否唯一的?
2、  它是否适用于所有记录?
3、  它是否使用最少的字段?
4、  随着时间的推移,它是否稳定?
       只要任意一个答案是否定的,都不应该设置为主键。
第一条跟第二条是主键的基本要求,保证了记录的唯一性和非空记录。尽管按书面理解,是允许有一条主键为NULL的记录的,但实际上Access中,主键是禁止为空的。
       第三条表示,主键应该是表中的单一字段。从多个字段创建复合主键将导致把表连接到其它表时出现难题,可以通过创建包含多个字段的索引来解决复合唯一性的需求,索引不一定是主键索引。
      稳定性是需要考虑的第四个条件。也就是说,必须要考虑到,如果需要二次开发的话,它是否不需要变更。
      例如,一家店可能卖几类产品,销量也是看每一类的销售总额。于是,就有同事以产品ID设置为成本表的主键。当然,一般情况下,同一类产品的成本都是一样的。就好比某个皮套棕色跟黑色可能都是58。但是也存在这种情况,金色耳机可能是24,其它颜色耳机可能 19。为此,他不得不把后面这类产品单独放置,统计前者再手动计算后者。
       这就是一个稳定性不好的例子。
       事实上,如果把成本细化到每个产品的每个颜色,以此作为主键,那么就可以省去了这个麻烦。因为每个产品的每个颜色是唯一的。


作者: djl52102    时间: 2015-7-18 12:37
顶一下,表的设计最基础,受教了
作者: 风中漫步    时间: 2015-7-18 14:17
谢谢分享
作者: cpxie    时间: 2015-7-23 07:07
学习了
作者: accben    时间: 2015-7-24 10:56
看了roych版好些文章相当不错(特别是ADO方面的介绍,我已收藏了),
roych版有不少的家底,强议建议roych版出书一本,引导菜鸟进阶ACCESS。

期待中......
作者: purplerose    时间: 2015-8-8 11:12
ROYCH 多谢了!!辛苦了{:soso_e156:}
作者: sgyzz    时间: 2015-8-12 16:00
学习了 多谢了!!
作者: coolcode    时间: 2016-5-13 10:53
很好,学习了
作者: coolcode    时间: 2016-5-13 11:19
1NF处理字段重复
作者: coolcode    时间: 2016-5-13 11:19
2NF处理记录重复
作者: panjie9327    时间: 2016-6-23 21:56
好帖学习了




欢迎光临 Office中国论坛/Access中国论坛 (http://www.office-cn.net/) Powered by Discuz! X3.3