您的位置:首页 > 数据库

数据库范式解析

2015-12-02 14:17 330 查看

前言

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

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

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

范式英语:Normal Form ,如果我们在设计关系型数据库过程中遵循一定的规范,那么我们的数据库设计就会冗余少。

现在数据库设计最多满足3NF,普遍认为范式过高,虽然具有对数据关系更好的约束性,但也导致数据关系表增加而令数据库IO更易繁忙。

每一级NF都有必须保证满足上一级NF。

概述

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

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

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

详解

1NF

1.1 解决的问题

排除重复组

1.2 例子

Table_交易

顾客日期数量
PeteMonday19.00 -28.20
PeteMonday-84.00
SarahFriday100.00 -48.20
数量就是“重复组”了。

1.3 解析

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

不过就算这样,你还是可以设计出骨子里违反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 例子

Table_组件来源

组件ID(主键)价格供应商ID(主键)供应商名称供应商住址
6559.991Stylized PartsVA
7420.001Stylized PartsVA
6569.992ACME IndustriesCA
1.3 解析

首先,上表是按多对一设计的(设计错误问题正是我们要说的),1个组件来自于1个供应商,1个供应商可能供应多个组件。

其次,上表满足了列的原子性,所以符合第一范式。组件ID和供应商ID是联合主键。

价格根据不同组件和不同供应商才能确定,没问题。

但供应商名称和供应商地址只是依赖于供应商ID的,跟组件没有关系,这就叫非完全依赖

一、正确设计

Table_供应商↓

供应商ID(主键)名称价格
1Stylized PartsVA
2ACME IndustriesCA
Table_组件来源↓

组件ID(主键)价格供应商ID(主键)
6559.991
7420.001
6569.992

3NF

1.1 解决的问题

在2NF基础上,非主键列必须直接依赖于主键。

1.2 解析

例子其实可以是上边2NF的列子,它也是不符合3NF的。

在做数据库表设计时,仔细考虑你写下的非关键字段到底是否直接依赖于主键,这样就能遵守第三范式了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: