序号 表名 说明
1 permission 权限表
2 user 用户表
3 menu 栏目表
4 news 新闻表
5 clicks 浏览信息表

ER图如下,并没有创建外键约束,因此本文中所有的外键都是指【逻辑外键】:

我们在数据库表设计时,经常说好的设计最起码要遵循第三范式,那现在用三大范式来检验一下我们的设计

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

数据库三大范式

设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。

目前关系数据库有8种范式(1NF,2NF,3NF,BCNF,4NF,5NF,DKNF,6NF),每一级范式都是基于前一范式的基础上,例如符合2NF的关系模式,必定符合1NF。一般说来,只需满足第三范式(3NF)就行了。

第一范式:所有属性都是不可分割的原子值

事实上,在目前的DBMS中是不可能拆分属性的。相对于excel来说,mysql的表并没有行合并和列合并的功能,因此从字面意思来看,我们的表很难违反第一范式!

第一范式包括下列指导原则:

1)关系中每个记录的每个属性只能包含一个值;                 ps:无法做到像Excel那样每个记录包含多个值。

2)关系中的每个记录必须包含相同数量的值;                  ps:无法做到像Excel那样每个记录包含不同数量的值

3)关系中的每个记录一定不能相同。                                 ps:要有主键约束或者唯一约束

我们每个表都用非业务主键id列,内容是GUID做主键,符合1NF。

第二范式:在第一范式的基础上,要求非主属性都要和码有完全依赖关系

这句话显然是针对复合主键联合主键来说的

1)复合主键:以clicks(id,ip,useragent,news_id,create_time)表为例,我们这里用了非业务主键id列,内容是GUID,避开了2NF。

为了研究2NF,我们删掉id列,再来看这个问题:

表的业务主键是(ip,news_id,create_time),即某ip在某时间浏览了某条新闻,而浏览器(useragent)是完全依赖于业务主键的,这符合2NF。如果我们在表中增加了一个news_title字段,那news_title是只依赖于news_id的,从而违反了2NF。

mysql中不应该使用具有实际意义的column 作为主键,这是因为主键列的值不建议进行修改。第一是因为主键列经常用作其他表的外键,如果某一表的主键被修改了,那牵一发而动全身。第二是考虑到经常更新的列不适合创建索引,这当然也包括mysql中的主键索引了。

这里我们的每个表都用GUID做主键,从而避免了使用复合主键,也避开了这种情况。

2)联合主键:

为了应对表间多对多的关系,需要创建中间表,在NewsDB中,权限表(permission)和用户表(user)就是多对多的关系。

创建中间表

permission_user(permission_id,user_id,create_time)

(permission_id,user_id)就是联合主键,如果这时候在要表中添加username列,那就违反了2NF,

真实的项目中,我们在user表中用了一个permission字段存储用户权限id,把用户的多个权限id用逗号隔开,从而免去了中间表,避免了违反第二范式的可能。这种做法能够成立,主要原因是权限的数量比较固定,而且后台用户数量很小。事实上我们每次对权限表的删除操作,要去更新所有的用户的permission字段,用以去除脏数据,这在用户量多的情况下,是很失败的做法。

比如,我们的新闻表(news)中同样有一个menus字段,用来存储新闻所属的栏目id,多个栏目id用逗号隔开。这里也没有采用中间表,就是很严重的设计问题了!我们应该使用中间表news_menus(id,news_id,menu_id)

除了上面讲的脏数据处理的问题,更主要的还是前台的查询性能问题,相比之下后台的所有功能都应该给它让路。要显示某栏目下的新闻,直接去中间表中查找对应的menu_id,即可筛选出所有的news_id,这变相的起到了索引表的效果。

反观是原来的方式,menus字段里多个栏目id用逗号隔开,我们就只能在where条件中用mysql中的locate()函数了(类似indexOf的功能),这显然是不能接受的。

这里添加中间表news_menus(id,news_id,menu_id)

第三范式:任何非主属性不依赖于其它非主属性。

这显然是针对外键来说的,这里以News表为例:

news(id,title,keywords,...,user_id,username,...state),username依赖于user_id,从而在表面上违反了第三范式。这里多存一个username主要是为了在用户被删除的情况下,还能取到用户名。这关系到后面的报表统计问题和应对可能发生的薪酬纠纷。

如果用户被删除,同时news表里只有一个user_id,那username就无从查起了。也就是说,现在即使把user表中的记录删除,news表中的username仍不受影响,这已经说明news表中的username字段并不依赖于user_id,因此这里并没有违反3NF。

我们还是以上面刚刚添加的新闻菜单表中间表news_menus(id,news_id,menu_id)为例,如果这时候在要表中添加news_title列,则违反了3NF

第二范式和第三范式的区别:

2NF针对复合主键和联合主键,表中属性存在部分依赖

3NF针对外键,在满足2NF的基础上,表中属性依赖于外键,造成传递依赖。

记住:

news_menus(news_id,menu_id,news_title)       违反2NF,部分依赖

news_menus(id,news_id,menu_id,news_title)    违反3NF,传递依赖

一般的在mysql都会用非业务主键,避开了部分依赖,反而造成了传递依赖出现的概率比较大!

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

最后修订的数据库: 

序号 表名 说明
1 permission 权限表
2 user 用户表
3 menu 栏目表
4 news 新闻表
5 news_menus 新闻_栏目表
6 clicks 浏览信息表

1、表名:permission(权限表)

序号 名称 数据类型 长度 小数位 允许空值 主键 默认值 说明
1 id varchar(45) 45 0 N Y   主键
2 name varchar(45) 45 0 Y     权限名称
3 orderby int 10 0 Y   0 排序
4 create_time datetime 23 0 Y   CURRENT_TIMESTAMP 创建时间

2、表名:user(用户表)

序号 名称 数据类型 长度 小数位 允许空值 主键 默认值 说明
1 id varchar(45) 45 0 N Y   主键
2 username varchar(45) 45 0 N     用户名
3 password varchar(45) 45 0 N     密码
4 permission varchar(200) 200 0 Y    

权限id

(多个用逗号隔开)

5 create_time datetime 23 0 Y   CURRENT_TIMESTAMP 创建时间

3、表名:menu(栏目表)

序号 名称 数据类型 长度 小数位 允许空值 主键 默认值 说明
1 id varchar(45) 45 0 N Y    
2 name varchar(45) 45 0 N     栏目名称
3 url varchar(200) 200 0 N     栏目url
4 orderby int 10 0 Y   0 排序字段
5 create_time datetime 23 0 Y   CURRENT_TIMESTAMP 创建时间

4、表名:news(新闻表)

序号 名称 数据类型 长度 小数位 允许空值 主键 默认值 说明
1 id varchar(45) 45 0 N Y   主键
2 title varchar(200) 200 0 N     标题
3 keywords varchar(200) 200 0 Y     关键词
4 menus varchar(200) 200 0 N     所属栏目(逗号隔开)
5 author varchar(45) 45 0 N     新闻来源
6 thumb varchar(200) 200 0 Y     缩略图
7 content text 65535 0 N     新闻内容
8 user_id varchar(45) 45 0 Y     创建人id
9 username varchar(45) 45 0 Y     创建人
10 create_time datetime 23 0 Y   CURRENT_TIMESTAMP 创建时间
11 edit_time datetime 23 0 Y     最后编辑时间
12 state tinyint 1 0 N   0

新闻状态

(0未发布1已发布)

5、表名:news_menus(新闻_栏目表)

序号 名称 数据类型 长度 小数位 允许空值 主键 默认值 说明
1 id varchar(45) 45 0 N Y    
2 news_id varchar(45) 45 0 N      
3 menu_id varchar(45) 45 0 N      

6、表名:clicks(浏览信息表)

序号 名称 数据类型 长度 小数位 允许空值 主键 默认值 说明
1 id varchar(45) 45 0 N Y    
2 ip varchar(45) 45 0 N     浏览人ip地址
3 useragent varchar(500) 500 0 Y     浏览器useragent
4 news_id varchar(45) 45 0 N     新闻id
5 create_time datetime 23 0 Y   CURRENT_TIMESTAMP 创建时间

跟着项目学sql(二) 三大范式相关推荐

  1. 跟着项目学sql——查询语句优化(一)

    现阶段,笔者的环境中只有SqlServer和Oracle.所以后面的文章更多的会以SqlServer的背景来做了. 来看这样一张表WorkLink: WorkLink表结构 WorkLink表数据,现 ...

  2. 跟着项目学设计模式(六):三层架构

    前面用5个章节介绍了单例模式和工厂系列模式,这个过程中,如果算上网站开发人员的表示层,那么项目经历了二层到多层的演变: 数据访问层+表示层 => 数据访问层+业务逻辑层+Client层+表示层 ...

  3. MySQL→数据库、启动连接数据库、SQL→DDL数据定义语言及数据类型、DML数据操作语言、DQL数据查询语言、数据库约束→主键、唯一、非空、默认、外键、SQL、三大范式及一多关系、视图、内外连接

    MySQL连接退出命令 mysql –uroot -proot mysql –h127.0.0.1 –uroot -proot mysql --host=localhost --user=root - ...

  4. 【跟着项目学CSS】第一期-闪动LOGO

    最近期末比较忙,没有上CSDN,没有回大家私信[非常对不起]. 进阶版JavaScript下周更新. 今天先浅浅学习一下CSS样式. 22 1.body代码 <body><div c ...

  5. mysql候选关键字_MySQL(三)之SQL语句分类、基本操作、三大范式

    一.SQL语句的分类 DML(Data Manipulation Langauge,数据操纵/管理语言) (insert,delete,update,select) DDL(Data Definiti ...

  6. SQL那些事儿(六)--数据库三大范式

    一.基本概念 函数依赖: 通俗描述: 描述一个学生的关系,可以有学号(SNO),姓名(SNAME),系名(SDEPT)等几个属性.由于一个学号只对应一个学生,一个学生只在一个系学习.因此当学号确定之后 ...

  7. 【狂神】SQL笔记9 --三大范式

    规范数据库设计 为什么需要设计 当数据库比较复杂的时候,就需要设计了 糟糕的数据库设计: 数据冗余,浪费空间 数据库插入和删除都会麻烦.异常[屏蔽使使用物理外键] 程序的性能差 良好的数据库设计 节省 ...

  8. 跟着实例学Go语言(二)

    本教程全面涵盖了Go语言基础的各个方面.一共80个例子,每个例子对应一个语言特性点,既适合新人快速上手,也适合工作中遇到问题速查知识点. 教程代码示例来自go by example,文字部分来自本人自 ...

  9. SQL语句以及三大范式

    SQL语句 登陆SQL 首先输入win+r+回车,之后输入mysql -u root -p,回车,之后输入自己的密码. 创建数据库 create database 表名 查看已有数据库 选择数据库 创 ...

最新文章

  1. 通过WMI获得硬盘和CPU的物理序列号(VB.net)
  2. 什么是embedding?
  3. win10 环境变量配置 如何在命令行运行php文件
  4. linux下core dump--转载
  5. 人活着系列之芳姐和芳姐的猪(Floyd)
  6. 小白2分钟学会Visual Studio将引用包打包到NuGet上
  7. windows cmd下的转义符
  8. GraphX:基于Spark的弹性分布式图计算系统
  9. html如何设置轮动,手把手教你构建轮动策略
  10. Intel 11代全新核显出现了!好强 好乱
  11. springboot系列二、springboot项目搭建
  12. 这道小学六年级的数学题,恕我直言没几个人会做
  13. 按键精灵可以实现c语言吗,按键精灵的原理和编写方法(1)
  14. 游戏服务端(MMORPG)的基础算法一、AOI
  15. 炎热夏季 本本散热板必不可少【lpxt】
  16. Class Test can not access a member of class User with modifiers “private“
  17. 【今日CV 计算机视觉论文速览 第96期】 8 Apr 2019
  18. VMware Workstation Pro虚拟机命令行安装图形界面
  19. 十六进制代码C语言,十六进制转换器C语言代码。怎么办?
  20. Android 资源汇总

热门文章

  1. 微信小程序之调试模式
  2. Linux的C开发环境
  3. 面向弹载图像的深度学习网络压缩方法研究
  4. 数据挖掘:汽车车交易价格预测(测评指标;EDA)
  5. 0欧姆电阻在电路中的作用
  6. Python自动化问卷填写-问卷星(含完整代码)
  7. matlab圆的检测,Hough圆检测的matlab实现 | 学步园
  8. angular-electron集成rxdb数据库
  9. 聊聊游戏:《空洞骑士》那些你不知道事
  10. LNMP架构安装及搭建Discuz论坛