前言

笔者遇到范式是在数据仓库建模时,以前对范式的理解比较浅显,且只了解前三范式,对后面三个范式并不了解,趁此机会和大家一起把其他范式学习下。

1. 基础概念

在了解范式之前我们需要对其中的一些基本概念进行了解。

1.1 候选码

某一属性组的值能唯一标识一个元组,而其子集不能,则称该属性组为候选码。若一个关系中有多个候选码,则选定其中一个为主码。
例如下图所示的学生表中,学号和姓名都可以唯一标识一个元组,故该表的候选码为学号和姓名,我们可以随便选定其中一个作为主码。

1.2 主属性

所有候选码的属性称为主属性。不包含在任何候选码中的属性称为非主属性或非码属性
在上面的学生表中,学号和姓名就是该关系的主属性,年龄和性别就是非主属性。

1.3 函数依赖


设R为任一给定的关系,如果对于R中属性X的每一个值,R中的属性Y只有唯一值与之对应,则称X函数决定Y或Y函数依赖于X,记作X——>Y。其中X称为决定因素。
通俗一点,就是给定一个X都有唯一的Y。可以理解为函数y=f(x);对于 任意的x 都有一个y,且y的取值有x决定。

例如:学号可以唯一确定一个学生的年龄、姓名等信息。

1.4 完全函数依赖

如果存在 X 属性组(注意是组,说明是联合主键)决定 唯一的 Y ,但 X 中的任一子集却不能决定唯一的 Y,则 Y 完全依赖于 X。
例如:学生的成绩由学生与课程共同决定。所以成绩完全依赖于学生与课程。

1.5 部分函数依赖

与完全函数依赖相反:如果存在 X 属性组(注意是组,说明是联合主键)决定 唯一的 Y ,且 X 中的任一子集都能能决定唯一的 Y,则 Y 部分依赖于X。
例如:在没有同名的情况下,学号与姓名都可以决定一个学生的年龄、性别等信息。

1.6 传递函数依赖

设 R 为任一给定关系, X Y Z 为其不同的属性子集,若 X —> Y 且 Y —>Z,则有 X —>Z,称为 Z 传递函数依赖于 X
例如:学号可以唯一确定一个系部,且系部可以唯一确定一个系主任。

2. 范式

2.1 什么是范式?

范式来自英文Normal form,简称NF。要想设计—个好的关系,必须使关系满足一定的约束条件,此约束已经形成了规范,这就是我们俗称的范式。范式分成几个等级,一级比一级要求得严格。各种范式呈递次规范,越高的范式数据库冗余越小。在设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,没有冗余的数据库未必是最好的数据库, 有时为了提高运行效率,就必须降低范式标准,适当保留冗余数据。

2.2 范式的分类

目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。各范式之间的联系如下:

如下图所示:

满足最低要求的范式是第一范式(1NF)。在第一范式的基础上进一步满足更多规范要求的称为第二范式(2NF),其余范式以次类推。一般说来,数据库只需满足第三范式(3NF)就行了。

2.2.1 第一范式(1NF)(针对具体某一列)

所谓第一范式(1NF)是指在关系模型中,对域添加的一个规范要求,所有的域都应该是原子性的,即数据库表的每一列都是不可分割的原子数据项,而不能是集合,数组,记录等非原子数据项。即实体中的某个属性有多个值时,必须拆分为不同的属性。在符合第一范式(1NF)表中的每个域值只能是实体的一个属性或一个属性的一部分。简而言之,第一范式就是无重复的域。

  • 不符合:
  • 符合:

实例:
例:下面这个表中张三其实是一个人,如果在一个java程序中应该是一个实体类,但是在数据库中记录成两条记录,因为tel列中包含了手机和宅电两个属性。

id name tel
1 张三 18656565656
2 张三 36522323

正确的方式是下面这样

id name tel phone
1 张三 36522323 18656565656

2.2.2 第二范式( 2NF )(针对某一列与复合主键的一部分有关)

  • 定义:
    所谓第二范式,是指所有的非主属性都完全依赖于关键字。
  • 理解:
    第二范式必须满足第一范式。
    第二范式是指每个关系必须有一个(有且仅有一个)数据项作为主键,其他数据项与主键一一对应,即其他数据项完全依赖于主键。由此可知单主属性的关系均属于第二范式。
  • 判断一个范式是否符合第二范式

实例:
例:假定选课关系表为SelectCourse(学号,姓名,年龄,课程名称,成绩,学分),关键字为组合关键字(学号,课程名称),因为存在如下决定关系:

stuId name age kemu score xuefen
1 张三 16 数学 89 100
2 张三 16 语言 90 100

age、name是由stuId决定的,与kemu无关;xuefen是由kemu决定的,与stuId无关;score是由stuId和kumu共决定的;即存在组合关键字中的字段决定非关键字的情况。由于不符合2NF,这个选课关系表会存在如下问题:

  1. 数据冗余:
    同一门课程由n个学生选修,"学分"就重复n-1次;同一个学生选修了m门课程,姓名和年龄就重复了m-1次。
  2. 更新异常:
    若调整了某门课程的学分,数据表中所有行的"学分"值都要更新,否则会出现同一门课程学分不同的情况。
  3. 插入异常:
    假设要开设一门新的课程,暂时还没有人选修。这样,由于还没有"学号"关键字,课程名称和学分也无法记录入数据库。
  4. 删除异常:
    假设一批学生已经完成课程的选修,这些选修记录就应该从数据库表中删除。但是,与此同时,课程名称和学分信息也被删除了。很显然,这也会导致插入异常。
    把选课关系表SelectCourse改为如下三个表:
    学生:Student(学号,姓名,年龄);
    课程:Course(课程名称,学分);
    选课关系:SelectCourse(学号,课程名称,成绩)。
    这样的数据库表是符合第二范式的, 消除了数据冗余、更新异常、插入异常和删除异常。

另外,所有单关键字的数据库表都符合第二范式,因为不可能存在组合关键字。

2.2.3 第三范式(3NF)(针对某一列与主键无关,但是与某一非主键列有关)

  • 定义:
    每一个非主属性既不部分依赖于也不传递依赖于关键字,也就是在第二范式的基础上消除传递依赖(A>B>C)。
  • 理解:
    即在第二范式的基础上,消除了非主属性对码的传递依赖。

实例:
例如,存在一个部门信息表,其中每个部门有部门编号(dept_id)、部门名称、部门简介等信息。那么在员工信息表中列出部门编号后就不能再将部门名称、部门简介等与部门有关的信息再加入员工信息表中。如果不存在部门信息表,则根据第三范式(3NF)也应该构建它,否则就会有大量的数据冗余。

2.2.4 BCNF(针对某一列与复合主键中的某一列有关,而与其他主键无关)

  • 定义:
    BCNF,是指在第三范式的基础上进一步消除主属性对于码的部分函数依赖和传递依赖。BCNF需要符合3NF,并且,主属性不依赖于主属性。所有属性都完全依赖于码,每一个决定因素都包含码。
  • 理解: 一个满足BC范式的关系模式有:
  1. 所有非主属性对每一个码都是完全函数依赖;
  2. 所有主属性对每一个不包含它的码也是完全函数依赖;
  3. 没有任何属性完全函数依赖于非码的任何一组属性。

例如有关系模式C(Cno, Cname, Pcno),Cno, Cname, Pcno依次表示课程号、课程名、先修课。可知关系C只有一个码Cno,且没有任何属性对Cno部分函数依赖或传递函数依赖,所以关系C属于第三范式,同时Cno是C中的唯一决定因素,所以C也属于BC范式。

实例:
假设仓库管理关系表为StorehouseManage(仓库ID,存储物品ID,管理员ID,数量),且有一个管理员只在一个仓库工作;一个仓库可以存储多种物品。这个数据库表中存在如下决定关系:
  
  (仓库ID,存储物品ID) →(管理员ID,数量)
  
  (管理员ID,存储物品ID) → (仓库ID,数量)
  
所以,(仓库ID,存储物品ID)和(管理员ID,存储物品ID)都是StorehouseManage的候选关键字,表中的唯一非关键字段为数量,它是符合第三范式的。但是,由于存在如下决定关系:

(仓库ID) → (管理员ID)

(管理员ID) → (仓库ID)

即存在关键字段决定关键字段的情况,所以其不符合BCNF范式。它会出现如下异常情况:

  1. 删除异常:
    当仓库被清空后,所有"存储物品ID"和"数量"信息被删除的同时,"仓库ID"和"管理员ID"信息也被删除了。
  2. 插入异常:
    当仓库没有存储任何物品时,无法给仓库分配管理员。
  3. 更新异常:
    如果仓库换了管理员,则表中所有行的管理员ID都要修改。
    把仓库管理关系表分解为二个关系表:
    仓库管理:StorehouseManage(仓库ID,管理员ID);
    仓库:Storehouse(仓库ID,存储物品ID,数量)。

这样的数据库表是符合BCNF范式的,消除了删除异常、插入异常和更新异常。

又如,有这样一个配件管理表WPE(WNO,PNO,ENO,QNT),其中WNO表示仓库号,PNO表示配件号,ENO表示职工号,QNT表示数量。

有以下约束要求:

  1. 一个仓库有多名职工;

  2. 一个职工仅在一个仓库工作;

  3. 每个仓库里一种型号的配件由专人负责,但一个人可以管理几种配件;

  4. 同一种型号的配件可以分放在几个仓库中。

分析表中的函数依赖关系,可以得到:

  1. (ENO)->WNO;

  2. (WNO,PNO)->QNT

  3. (WNO,PNO)->ENO

  4. (ENO,PNO)->QNT

可以看到,候选键有:(ENO,PNO);(WNO,PNO)。所以,ENO,PNO,WNO均为主属性,QNT为非主属性。显然,非主属性是直接依赖于候选键的。所以此表满足第三范式。

而我们观察一下主属性:(WNO,PNO)->ENO;ENO->WNO。显然WNO对于候选键(WNO,PNO)存在传递依赖,所以不符合BCNF.

解决这个问题的办法是分拆为两个表:管理表EP(ENO,PNO,QNT);工作表EW(ENO,WNO)。但这样做会导致函数依赖(WNO,PNO)->ENO丢失。

虽然,不满足BCNF,也会导致一些冗余和一致性的问题。但是,将表分解成满足BCNF的表又可能丢失一些函数依赖。所以,一般情况下不会强制要求关系表要满足BCNF。

2.2.5 4NF(第四范式)

  • 定义:
    第四范式,从理论层面来讲是,关系模式R∈1NF,如果对于R对于R的每个非平凡多值依赖X→→Y(Y不属于X),X都含有候选码,则R∈4NF。4NF就是限制关系模式的属性之间不允许有非平凡且非函数依赖的多值依赖。显然一个关系模式是4NF,则必为BCNF。
  • 理解:
    显然一个关系模式是4NF,则必为BCNF。也就是说,当一个表中的非主属性互相独立时(3NF),这些非主属性不应该有多值,若有多值就违反了4NF。

实例:
有这样一个用户联系方式表TELEPHONE(CUSTOMERID,PHONE,CELL)。CUSTOMERID为用户ID,PHONE为用户的固定电话,CELL为用户的移动电话。

本来,这是一个非常简单的第3范式表。主键为CUSTOMERID,不存在传递依赖。但在某些情况下,这样的表还是不合理的。比如说,用户有两个固定电话,两个移动电话。这时,表的具体表示如下:

CUSTOMERID PHONE CELL
1000 8828-1234 149088888888
1000 8838-1234 149099999999

由于PHONE和CELL是互相独立的,而有些用户又有两个和多个值。这时此表就违反第四范式。

在这种情况下,此表的设计就会带来很多维护上的麻烦。例如,如果用户放弃第一行的固定电话和第二行的移动电话,那么这两行会合并吗?等等

解决问题的方法为,设计一个新表NEW_PHONE(CUSTOMERID,NUMBER,TYPE).这样就可以对每个用户处理不同类型的多个电话号码,而不会违反第四范式。

显然,第四范式的应用范围比较小,因为只有在某些特殊情况下,要考虑将表规范到第四范式。所以在实际应用中,一般不要求表满足第四范式。

2.2.6 5NF(第五范式)

  • 第五范式(5NF):是最终范式。消除了4NF中的连接依赖。

  • 第五范式有以下要求:

  1. 必须满足第四范式
  2. 表必须可以分解为较小的表,除非那些表在逻辑上拥有与原始表相同的主键。

第五范式是在第四范式的基础上做的进一步规范化。第四范式处理的是相互独立的多值情况,而第五范式则处理相互依赖的多值情况。

实例:
有一个销售信息表SALES(SALEPERSON,VENDOR,PRODUCT)。SALEPERSON代表销售人员,VENDOR代表供和商,PRODUCT则代表产品。
在某些情况下,这个表中会产生一些冗余。可以将表分解为PERSON_VENDOR表(SALEPERSON,VENDOR);PERSON_PRODUCT表(SALEPERSON,PRODUCT);
VENDOR­_PRODICT表(VENDOR,PRODUCT)

数据库理论 —— 数据库设计六大范式相关推荐

  1. DataBase 之 数据库设计六大范式

    范式是符合某一种级别的关系模式的集合.关系数据库中的关系必须满足一定的要求,即满足不同的范式. 目前关系数据库有六种范式:第一范式(1NF).第二范式(2NF).第三范式(3NF).第四范式(4NF) ...

  2. 数据库设计的范式规范

    关系型数据库的设计遵循六大范式:第一范式(1NF).第二范式(2NF).第三范式(3NF).巴斯-科德范式(BCNF).第四范式(4NF)和第五范式(5NF,又称完美范式). 第一范式 1NF 1NF ...

  3. 数据库 之数据库设计浅知识 -- 设计概述、概念结构设计(E-R模型概述)、逻辑结构设计(函数依赖和范式)、物理结构设计

    文章目录 1. 数据库设计概述 1.1 数据库设计的特点:结构和行为分离的设计 1.2 数据库设计方法 1.3 数据库设计的基本步骤 1.4 数据库设计过程中的各级模式 2. 需求分析 2.1 需求分 ...

  4. 数据库设计三大范式和ER模型

    1. 数据库设计之三范式的介绍 范式: 对设计数据库提出的一些规范,目前有迹可寻的共有8种范式,一般遵守3范式即可. 第一范式(1NF): 强调的是列的原子性,即列不能够再分成其他几列.(1NF强调字 ...

  5. 数据库设计三大范式应用实例剖析(转载)

    引言 数据库的设计范式是数据库设计所需要满足的规范,满足这些规范的数据库是简洁的.结构明晰的,同时,不会发生插入(insert).删除(delete)和更新(update)操作异常.反之则是乱七八糟, ...

  6. (转载)简洁、明晰!数据库设计三大范式应用实例剖析

    (转载http://bbs.database.ccidnet.com/read.php?tid=325895) 简洁.明晰!数据库设计三大范式应用实例剖析 引言OL~eR{q   ;iC,$vZ 0} ...

  7. 数据库设计三大范式应用实例剖析

    引言 数据库的设计范式是数据库设计所需要满足的规范,满足这些规范的数据库是简洁的.结构明晰的,同时,不会发生插入(insert).删除(delete)和更新(update)操作异常.反之则是乱七八糟, ...

  8. 数据库设计三大范式应用实例剖析(讲得比较清楚)

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 转贴地址 ...

  9. 数据库设计三范式(3NF)

    问:当时你数据库是如何设计的? 答:当时是按照三范式规范设计的: 第一范式: 1:数据库的原子性,即保证数据库表的每一列都不可分割的 第二范式: 1:原子性,即保证数据库表的每一列都不可分割 2:表中 ...

最新文章

  1. 03-NSPredicate谓词
  2. js进阶正则表达式方括号(方括号作用)(js正则是在双正斜杠之中:/[a-z]/g)...
  3. CentOS 7 安装Golang
  4. Tomcat虚拟主机配置
  5. c# 定位内存快速增长_CTF丨Linux Pwn入门教程:针对函数重定位流程的相关测试(下)...
  6. php 自动验证 正则表达,使用正则表达式验证登录页面的输入内容
  7. linux tcp 创建,Linux下tcp服务器创建的步骤
  8. java——获取视频某一帧的图片
  9. oracle 建分区索引_ORACLE 创建组合分区索引
  10. java中抛出异常快捷键_idea中处理异常的快捷键
  11. request.getContextPath()和request.getRealPath()的区别
  12. 大数斐波那契数列(nyoj655)光棍的yy
  13. UniBeast:在任何支持基于英特尔处理器的PC上安装OS X优胜美地
  14. 2021年社工必备查询网址汇总
  15. php 360 检测,检测某个链接是否被360搜索引擎收录
  16. SpringMVC之405错误码
  17. Android连接SQLServer详细教程(数据库+服务器+客户端),并在微软Azure云上搭建云服务
  18. fastjson使用toJSONString时null值不序列化问题
  19. 使用restTemplate启动报错:Field restTemplate in com.demo.service.OrderToMemberService required a bean of ty
  20. Kinetics-400数据集下载

热门文章

  1. html实现类似app的欢迎页,css3动画代替js脚本实现欢迎页面动画
  2. sendmail报错:“My unqualified host name ( name ) unknown; sleeping for retry“
  3. 京东店铺如何通过主图提高点击率?
  4. php mysql utf8mb4,MySQL设置utf8mb4编码
  5. Origin2021科研绘图神器
  6. Learning Photoshop Portrait Retouching 学习Photoshop肖像修饰 Lynda课程中文字幕
  7. docker启动容器慢,很慢,特别慢的坑
  8. 音视频开发——音视频学习资料
  9. js合并两个数组的三种方法
  10. 使用fdisk结合partprobe命令不重启系统添加 一块新的磁盘分区