zoukankan      html  css  js  c++  java
  • 【转】数据库范式(1NF 2NF 3NF BCNF)

    范式判断流程图

    1. 四种范式之间关系 

            

    2.第二范式、第三范式、BCNF区别:

    2NF:非主键列和主键列之间,是完全依赖于主键,还是依赖于主键的一部分(只依赖某个主键);

    3NF:非主键列之间,不存在依赖,只直接依赖主键。

    BCNF:主键列之间,不存在依赖。

    一般关系数据库都满足第一范式,先确定是几个主键属性。

    第一范式:列不可再分

    第二范式:非主键属性全部依赖于主键属性

    第三范式:非主键属性之间无依赖关系

    第四范式:主键属性之间无依赖关系

    3. 第一范式:列不可分。每一列都是不可分割的基本数据项。

    a.反例:

    StudyNo

    Name  

    Sex  

    Contact

    20040901     

    john        

    Male     

    Email:kkkk@ee.net,phone:222456

    20040902     

    mary        

    famale   

    email:kkk@fff.net phone:123455

    contact字段可以再分,不符合第一范式。

    b.  正解:

    StudyNo

    Name  

    Sex  

    Email

    Phone

    20040901     

    john        

    Male     

    Email:kkkk@ee.net

    222456

    20040902     

    mary        

    famale   

    email:kkk@fff.net

    123455

    4.第二范式:在第一范式基础上,对于多关键字表,非主属性不能部分依赖于主键(eg:只依赖某个主键);对于单关键字表,不存在部分依赖情况(只依赖一个主键,全部依赖),全符合。

    better eg:

    订单明细表:【OrderDetail】(OrderID,ProductID,UnitPrice,Discount,Quantity,ProductName)。
    因为我们知道在一个订单中可以订购多种产品,所以单单一个 OrderID 是不足以成为主键的,主键应该是(OrderID,ProductID)。显而易见 Discount(折扣),Quantity(数量)完全依赖(取决)于主键(OderID,ProductID),而 UnitPrice,ProductName 只依赖于 ProductID。所以 OrderDetail 表不符合 2NF。不符合 2NF 的设计容易产生冗余数据。
    可以把【OrderDetail】表拆分为【OrderDetail】(OrderID,ProductID,Discount,Quantity)和【Product】(ProductID,UnitPrice,ProductName)来消除原订单表中UnitPrice,ProductName多次重复的情况。

     a.反例:

    StudyNo

    Name  

    Sex  

    Email

    Phone

    ClassNo

    ClassAddress

    20040901     

    john        

    Male     

    Email:kkkk@ee.net

    222456

    200401

    #12A

    20040902     

    mary        

    famale   

    email:kkk@fff.net

    123455

    200402

    #8A

    主键是studyNo和classNo。classAddress部分依赖主键classNo,需要变为两个表。

    b.  正解:

    学生表

    StudyNo

    Name  

    Sex  

    Email

    Phone

    20040901     

    john        

    Male     

    Email:kkkk@ee.net

    222456

    20040902     

    mary        

    famale   

    email:kkk@fff.net

    123455

    教室表

    ClassNo

    ClassAddress

    200401

    #12A

    200402

    #8A

    c. 消除数据冗余和增、删、改异常。

    (1) 数据冗余:

        同一门课程由n个学生选修,"学分"就重复n-1次;同一个学生选修了m门课程,姓名和年龄就重复了m-1次。

    (2) 更新异常:

        若调整了某门课程的学分,数据表中所有行的"学分"值都要更新,否则会出现同一门课程学分不同的情况。

    (3) 插入异常:

        假设要开设一门新的课程,暂时还没有人选修。这样,由于还没有"学号"关键字,课程名称和学分也无法记录入数据库。

    (4) 删除异常:

        假设一批学生已经完成课程的选修,这些选修记录就应该从数据库表中删除。但是,与此同时,课程名称和学分信息也被删除了。很显然,这也会导致插入异常。

    5.第三范式:在第二范式基础上,非关键字段对任一主键不能传递函数依赖。非主键列必须直接依赖于主键,不能传递依赖。即不能存在:非主键列 A 依赖于非主键列 B,非主键列 B 依赖于主键的情况。总之,非主键列之间不能存在依赖关系。

    better eg:

    订单表【Order】(OrderID,OrderDate,CustomerID,CustomerName,CustomerAddr,CustomerCity)主键是(OrderID)。
    其中 OrderDate,CustomerID,CustomerName,CustomerAddr,CustomerCity 等非主键列都完全依赖于主键(OrderID),所以符合 2NF。不过问题是 CustomerName,CustomerAddr,CustomerCity 直接依赖的是 CustomerID(非主键列),而不是直接依赖于主键,它是通过传递才依赖于主键,所以不符合 3NF。
    通过拆分【Order】为【Order】(OrderID,OrderDate,CustomerID)和【Customer】(CustomerID,CustomerName,CustomerAddr,CustomerCity)从而达到 3NF。

    a. 反例:

    StudyNo

    Name  

    Sex  

    Email

    Phone

    BounsLevel

    Bouns

    20040901     

    john        

    Male     

    Email:kkkk@ee.net

    222456

    优秀

    ¥1200

    20040902     

    mary        

    famale   

    email:kkk@fff.net

    123455

    ¥800

    主键是StudyNo,只有一个主键StudyNo,而且符合第二范式。但是非主键列bounsLevel和bouns存在依赖关系。

    b.正解:

    学生表

    StudyNo

    Name  

    Sex  

    Email

    Phone

    BounsNo

    20040901     

    john        

    Male     

    Email:kkkk@ee.net

    222456

    1

    20040902     

    mary        

    famale   

    email:kkk@fff.net

    123455

    2

    奖学金等级表

    BounsNo

    BounsLevel

    Bouns

    1

    优秀

    ¥1200

    2

    ¥800

    c.消除数据冗余和增、删、改异常。

    6.鲍依斯-科得范式(BCNF):在第三范式的基础上,数据库表中如果不存在任何字段对任一候选关键字段的传递函数依赖则符合第三范式。即不存在关键字段决定关键字段的情况。

    a.反例:StoreHouseManager

    StoreHouseID(仓库ID)

    GoodsID(商品ID)

    ManagerID(管理员ID)

    GoodsNum(商品数量)

    001

    20130104

    1

    200

    主键是

    (仓库ID, 商品ID) →(管理员ID, 数量) 或

    (管理员ID, 商品ID) → (仓库ID, 数量),

    (仓库ID, 商品ID)和(管理员ID,商品ID)都是StorehouseManage的候选关键字,表中的唯一非关键字段为数量

    满足第三范式。但是,存在关键字段决定关键字段情况。

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

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

    b.正解:

    仓库管理表

    StoreHouseID(仓库ID)

    GoodsID(商品ID)

    GoodsNum(商品数量)

    001

    20130104

    200

    仓库表

    StoreHouseID(仓库ID)

    ManagerID(管理员ID)

    001

    1

    c. 消除增、删、改异常。

    (1) 删除异常:

    当仓库被清空后,所有"存储物品ID"和"数量"信息被删除的同时,"仓库ID"和"管理员ID"信息也被删除了。

    (2) 插入异常:

    当仓库没有存储任何物品时,无法给仓库分配管理员。

    (3) 更新异常:

    如果仓库换了管理员,则表中所有行的管理员ID都要修改。 

    应用的范式等级越高,则表越多。表多会带来很多问题:
    1 查询时要连接多个表,增加了查询的复杂度
    2 查询时需要连接多个表,降低了数据库查询性能
    而现在的情况,磁盘空间成本基本可以忽略不计,所以数据冗余所造成的问题也并不是应用数据库范式的理由。
    因此,并不是应用的范式越高越好,要看实际情况而定。第三范式已经很大程度上减少了数据冗余,并且减少了造成插入异常,更新异常,和删除异常了。所以大多数情况应用到第三范式已经足够,在一定情况下第二范式也是可以的。

  • 相关阅读:
    cnblog项目--20190309
    django js引入失效问题
    Python老男孩 day16 函数(六) 匿名函数
    Python老男孩 day16 函数(五) 函数的作用域
    Python老男孩 day15 函数(四) 递归
    Python老男孩 day15 函数(三) 前向引用之'函数即变量'
    Python老男孩 day15 函数(二) 局部变量与全局变量
    Python老男孩 day14 函数(一)
    Python老男孩 day14 字符串格式化
    Python老男孩 day14 集合
  • 原文地址:https://www.cnblogs.com/shawWey/p/8960746.html
Copyright © 2011-2022 走看看