zoukankan      html  css  js  c++  java
  • mysql数据库的三范式的设计与理解

    一般的数据库设计都需要满足三范式,这是最基本的要求的,最高达到6NF,但是一般情况下3NF达到了就可以

    一:1NF一范式的理解:

    1NF是关系型数据库中的最基本要求,就是要求记录的属性是原子性,不可分,就是属性不能分,这是关系型数据库的基本要求,不满足这个就不能叫关系型数据库了

    例如:

    讲师 性别 班级 教室 代课时间 代课时间(开始,结束)
    韩忠康 Male php0331 102 30天 2013-03-31,2013-05-05
    韩忠康 Male php0228 106 30天 2013-02-28,2013-03-30
    韩顺平 male Php0228 106 15天 2013-03-31,2013-05-05

    上面的代课时间字段设计就不满足原子性,因为它可以再分的,开始时间和结束时间,需要按照下面来设计拆分:

    讲师 性别 班级 教室 代课时间 开始 结束
    韩忠康 Male php0331 102 30天 2013-03-31 2013-05-05
    韩忠康 Male php0228 106 30天 2013-02-28 2013-03-30
    韩顺平 male Php0228 106 15天 2013-03-31 2013-04-20

    上面的就满足了,但是有些时候也需要去违背这个1NF的设计:在用dede设计cms的时候后台的下载地址是将格式,名称,分辨率这些进行评级在一个属性里面,但是可以看作一个整体,因为这个属性即使分开,那么各个成员的关系不是平等的,但是代课时间是不一样的,比如分为开始时间和结束时间,两个成员的关系基本一样!所以也不矛盾!

    二:2NF二范式的理解

    2NF是不能有部分依赖,部分依赖的前提条件是有组合主键,就是每条记录是需要一个主键的,这个主键可以是一个单独的属性,但也可以是组合主键,就是由记录的多个属性来唯一确定一条记录,那么只要出现了组合主键就可以产生部分依赖,部分依赖是组合主键出现的前提下,剩余的属性,不完全依赖于组合主键,也是部分依赖组合主键,比如该表的N条记录中由组合主键中的一条或者几条就可以确定剩余属性的属性,那么就可以说产生部分依赖,而在实际开发中,一般不采用组合主键,而是自己增加一个字段id自增长,作为主键,这样的单属性主键是不会产生部分依赖的!

    例如:

    讲师P 性别 班级P         教室 代课时间 开始 结束
    韩忠康 Male php0331 102 30天 2013-03-31 2013-05-05
    韩忠康 Male php0228 106 30天 2013-02-28 2013-03-30
    韩顺平 male Php0228 106 15天 2013-03-31 2013-04-20

    上面的设计可以用讲师P,班级,两个字段作为组合主键,但是问题来了,那么后面的教室仅仅由班级字段(组合主键中的一条)就可以确定,即所谓教室部分依赖于组合主键,那么就不符合2NF

    应该按照下面就行设计:

    IDP 讲师 性别 班级 教室 代课时间 开始 结束
    1 韩忠康 Male php0331 102 30天 2013-03-31 2013-05-05
    2 韩忠康 Male php0228 106 30天 2013-02-28 2013-03-30

    可以看到仅仅增加一个主键IDP就不存在部分依赖了,这是实际项目中开发中常用的手段!

    三:3NF的理解:不能出现传递依赖:就是主键,非主键1,非主键2三者之间不能出现传递依赖关系,如果出现由主键可以推出非主键1,然后由非主键1可以推出非主键2,那么主键与非主键2就产生了传递依赖关系,这就不满足三范式,通俗来讲,在一个表的,当然以一条记录为单位,主键和非主键之间可以产生父子关系,但是非主键之间是不能出现父子关系的!

    例如:

    IDP 讲师 性别 班级 教室 代课时间 开始 结束
    1 韩忠康 Male php0331 102 30天 2013-03-31 2013-05-05
    2 韩忠康 Male php0228 106 30天 2013-02-28 2013-03-30
    3 韩顺平 male php0228 106 15天 2013-03-31 2013-04-20

    上面的设计不满足3NF:

    主键1--推出--->班级php0331,班级php0331-----推出---->教室102,这样给人的感觉,教室不是由主键IDP1直接推出的,好像由班级通过传递推出的;当然还存在

    主键IDP---->讲师------>性别

    这样的坏处就是会产生数据冗余,解决方案是把中间的代理抽出来作为另外一张表:

    应该如下设计:

    IDP 讲师 班级 代课时间 开始 结束
    1 韩忠康 php0331 30天 2013-03-31 2013-05-05|
    2 韩忠康 php0228 30天 2013-02-28 2013-03-30|
    3 韩顺平 php0228 15天 2013-03-31 2013-04-20|

    --------------------------------------------------------

    讲师 性别
    韩忠康 male
    韩顺平 male

    -----------------


    班级 教室

    php0228 106

    php0331 102

    -------------

    可以看到这样设计只需要用22个字段,而上面那种设计需要用24个字段,这样就节省了2个字段,如果数据是海量的那么节省的数据应该更加多

    这样设计,其实为了避免非笛卡尔积数据的重复,当然,笛卡尔积的数据的重复是必须的!

    那么数据库的设计可以先按照自己的想法设计一个"大表"出来,然后进行拆分成符合三范式的表,当然一般的规律的实体都单独作为一个表格

    比如讲师实体,班级实体,代课关系实体,但是最大的问题是开始不知道哪些是实体,其实除了看得见的,其实说的清的可以描述的关系也可以作为一个实体

    ,这一点是容易被忽视的,但是随着经验的提升,慢慢会了解!

  • 相关阅读:
    Leetcode: Rotate Image
    Leetcode: Longest Palindromic Substring && Summary: Palindrome
    Leetcode: Reverse Nodes in k-Group
    Leetcode: Substring with Concatenation of All Words
    Leetcode: Merge k Sorted List
    Summary: Java中函数参数的传递
    Leetcode: Generate Parentheses
    超级wifi
    路由器中继(repeater)模式 和 AP+WDS模式区别?
    route 的标志位
  • 原文地址:https://www.cnblogs.com/sengling/p/5219490.html
Copyright © 2011-2022 走看看