数据库范式解析

前言

前段时间自己写项目,在设计数据库的过程中,重新审视了关系型数据库,在此记录整理如下。

但是只有通过实际开发,并在其中运用、体会才能深刻学习和领会到前辈们创造的理论的优美!

什么是关系型数据库的范式?

  1. 范式英语:Normal Form ,如果我们在设计关系型数据库过程中遵循一定的规范,那么我们的数据库设计就会冗余少。
  2. 现在数据库设计最多满足3NF,普遍认为范式过高,虽然具有对数据关系更好的约束性,但也导致数据关系表增加而令数据库IO更易繁忙。
  3. 每一级NF都有必须保证满足上一级NF。

概述

1NF:列的原子性,不可再分;

2NF:非主键列必须完全依赖于主键;

3NF:非主键列必须直接依赖于主键列,不能存在传递依赖(传递依赖:非主属性A依赖非主属性B,B再依赖主属性C);

详解

1NF

1.1 解决的问题

排除重复组

1.2 例子

Table_交易

顾客 日期 数量
Pete Monday 19.00 -28.20
Pete Monday -84.00
Sarah Friday 100.00 -48.20

数量就是“重复组”了。

1.3 解析
  1. 理论上不可能有RDBMS能让你设计出违反1NF的数据表,也就是说RDBMS已经保证其列的原子性了。例如,你定义了一个整数字段来存放数量,你肯定写不出”25,30”这样的值,它是违法的(如果你硬把2530连着写,那表示这是一个原子值)。

  2. 不过就算这样,你还是可以设计出骨子里违反1NF的表,例如

    一、单一字段中有多个有意义的值
    Table_不喜欢的食物

    不喜欢的食物(varchar类型)
    Pete 白菜,面包
    Pete 泡菜,白菜,西兰花

    a) 显然“不喜欢的食物”是一个RDBMS保证的原子列,但是你利用他是varchar这一点,来自己意淫设计存储了多个逻辑值,然后用逗号分隔他们…… 相信很多人这样干过
    b) 以这样的设计,如果要查询不喜欢白菜的人就很不清晰该怎么做了(还能叫关系型数据库表吗)可能必须使用like%%了。

    二、用很多字段来表达一个事实
    Table_不喜欢的食物

    不喜欢的食物1 不喜欢的食物2 不喜欢的食物3
    Pete 白菜 小龙虾 芹菜
    Alan 泡菜 龙虾 大闸蟹

    a) 就算我们能确定每个人不喜欢吃的食物最多不会超过三样,这还是一个很糟的设计。举例来说,我们想要知道所有不喜欢同一种食物的人的组合的话,这就不是件容易的事,因为食物有可能出现在任何一个字段,也就是说每一次的查询都要去检查 9 (3 x 3) 组不同的字段组合。

2NF

1.1 解决的问题
  1. 如果一个数据表只有单一一个主键字段的话,它就一定符合第二范式。
  2. 错误一般只会发生在想设计有一对多/多对一中多的一方或者是多对多关联表中的联合主键时发生。
1.2 例子

Table_组件来源

组件ID(主键) 价格 供应商ID(主键) 供应商名称 供应商住址
65 59.99 1 Stylized Parts VA
74 20.00 1 Stylized Parts VA
65 69.99 2 ACME Industries CA
1.3 解析
  1. 首先,上表是按多对一设计的(设计错误问题正是我们要说的),1个组件来自于1个供应商,1个供应商可能供应多个组件。
  2. 其次,上表满足了列的原子性,所以符合第一范式。组件ID和供应商ID是联合主键。
  3. 价格根据不同组件和不同供应商才能确定,没问题。
  4. 但供应商名称和供应商地址只是依赖于供应商ID的,跟组件没有关系,这就叫非完全依赖

    一、正确设计
    Table_供应商↓

    供应商ID(主键) 名称 价格
    1 Stylized Parts VA
    2 ACME Industries CA

    Table_组件来源↓

    组件ID(主键) 价格 供应商ID(主键)
    65 59.99 1
    74 20.00 1
    65 69.99 2

3NF

1.1 解决的问题
  1. 在2NF基础上,非主键列必须直接依赖于主键。
1.2 解析
  1. 例子其实可以是上边2NF的列子,它也是不符合3NF的。
  2. 在做数据库表设计时,仔细考虑你写下的非关键字段到底是否直接依赖于主键,这样就能遵守第三范式了。

你可能感兴趣的:(数据库,范式)