• 关系型数据库:设计范式介绍


    范式简单说明

    • 1NF:每一列都是不可分割的原子数据项
    • 2NF:消除非主属性对码的部分函数依赖
    • 3NF:消除非主属性对码的传递函数依赖

    详细解析查看百度百科:数据库范式

    如何理解这几个范式的含义?光看字面意思就非常的晦涩!

    这几种范式有什么意义呢?可以简单理解为是一种设计标准。

    一般我们是如何设计表字段呢? 似乎并没有什么硬性的要求,可以把一个表搞成几个表,反过来也行;

    几十个字段放一起也行,拆分在不同的地方也行。但是,这种随心所欲的设计,项目是走不长远的  

    1NF:每一列都是不可分割的原子数据项

    1NF理解起来比较容易,关系型数据库一般都满足这个,是关系型数据库最基本的要求了。

    即每一列所代表的数据属性是不可再分的,就像原子一眼,已经是物质构成的最小单位。如下图:

    图1

    商品类型列包涵了2种属性:分类ID与名称;

    这在数据库表中是不可能存在的,即取数据的时候“商品类型”这一列不可能即代表名称又代表ID,符合1NF要求的表应该如下:

    图2

    这样设计就比较清晰明了了;1NF比较好理解,一般都不会犯错误这种错误,但也不排除例外的。

    比如难道就不能按照一定格式存储吗,比如这样:分类ID|分类名称、或这样:{cls=分类ID,title=名称}

    当然可以那样做!你把“分类ID与类型名称”hash取值再取模再平方都可以。但那样就算是破坏了规则了,旁门左道说的就是如此。

    好了,我们的表也已经符合1NF了, 是不是这样就万事大吉了呢?我们来试试看;

    1、查看每一行数据,发现商品名称、分类ID、类型名称等信息重复多次,数据冗余太大了,待改进!

    2、新增记录,假设新设置了一个分类,前台维护数据会发生什么情况呢?

    根据图2可以得知,表中的码(就是确定唯一一行数据的一个或多个属性(字段))是:商品ID+日期,根据这个码,才可以区分数据表中的每一条记录

    也就是说,这个码是非空的!你现在新增一个分类,码的信息都还没有,那就会直接导致插入异常,待改进 

    3、修改记录,现在“名称1”的分类改变了,分类1要改成分类2;

    发现有多少条“名称1”的记录就得把对应的分类1改成分类2,如果有上万条记录,估计鼠标都得换好几个,待改进

    4、删除记录,现在商品“名称1”下架了,得删除与之相关的信息,发现连分类、销售额等信息都被删掉了,待改进

    问题这么多,这完全是胡乱设计导致的结果,怎么办才能避免这种结果呢,于是有了2NF

    2NF:消除非主属性对码的部分函数依赖

    这句话有几个名称需要解析一下:

    1、主属性,可以理解为码的子集;码就是由一个或多个主属性组成的;

    2、非主属性,那当然就是主属性之外的所有字段咯。。

    3、部分函数依赖,首先函数依赖可以参考数学里的方程式:y = f(x),即自变量x明确的情况下,y是明确可知的。

    那这里说的部分函数依赖是什么意思呢,根据图2看下图

    图3

    参照上图, y = f(x) 可理解为:非主属性 = f(码),即码确定的情况下,那些非主属性肯定能获取到。

    这个部分函数依赖,指的是部分非主属性对码的部分主属性产生依赖,有哪些呢?

    很明显:右边的非主属性只对商品ID产生依赖,跟日期无关;

    既然要求符合2NF,那就要消除这种部分依赖;那我们就只能拆表了,如下:

    图4

    数据表也改好了,我们再看看会不会还有问题。现在各表的码如下:

    表1:码(商品ID+日期),非主属性“销售额”已经完全依赖于码,不存在部分依赖了

    表2:码(商品ID),非主属性也是完全依赖于码

    1、查看表2,变成基础数据了,每个员工只有一条记录;查看表1,发现名称、分类等信息没有了,冗余少了很多,有改进!

    2、新增记录,还是新增新分类,而表2的码是“商品ID”,新增的分类显然不关员工的“商品ID”啥事,还是会插入异常,待改进!

    3、修改记录,还是商品1改分类,因为拆表了,所以在表2把商品1对应的分类1改成分类2就行了,只改了一行数据就搞定!有改进!

    4、删除记录,删除商品1相关信息,发现分类还是被删掉了,待改进!

    看来拆表了还是没有完全解决问题呀,为什么会这样呢,非主属性已经完全依赖于码了呀?于是3NF出场了 

    3NF:消除非主属性对码的传递函数依赖

    非主属性:这个不用多说了,上面已经解析过。 

    传递函数依赖:这个可以理解为2个或多个函数依赖组成的,如:A=f(B) , B = f(C),则 A = T(C)

    即由C可得到B,由B可得到A,那由C可得到A,中间多了一层。

    图4存在哪些传递依赖关系呢,如下:

    在商品ID确定的情况下,可得到分类ID,再由分类ID得到分类名称,这就是所谓的传递函数依赖

    我们再继续拆表,如下:

    图5

    好了,现在看看表1、2、3;完全都符合要求,即是原子性,又没有部分函数依赖,也没有传递函数依赖; 

    1、完全没有数据冗余,数据很简洁

    2、新增记录,新增分类,改动的只是分类基础数据表,跟其他表无关。有改进!

    3、修改记录,商品1改分类,只改动商品基础数据表,跟其他表无关。有改进!

    4、删除记录,删除商品1相关记录, 删除的也是商品基础数据表,和销售表与分类表无关。有改进!

  • 相关阅读:
    记录idea run dashboard设置 (微服务项目多服务启动)
    记录Java8中的字符串转数组再通过指定符号拼接
    Java 调用底层接口的几种方法
    工作两个月以后的感想
    几种开源工作流引擎的简单比较
    labin编译的另一种方式
    最近参加一个团队创业项目的感触
    gof设计模式——生成器c++实现
    gof设计模式——抽象工厂 c++实现
    几种开源网络爬虫的简单比较
  • 原文地址:https://www.cnblogs.com/lanxiaoke/p/6414580.html
Copyright © 2020-2023  润新知