一、题目
三大范式
二、三大范式
第一范式(1NF):属性不可分割,即每个属性都是不可分割的原子项
第二范式(2NF):满足第一范式;且不存在部分依赖,即非主属性必须完全依赖于主属性(主属性即主键)
第三范式(3NF):满足第二范式;且不存在传递依赖,即非主属性不能与非主属性之间有依赖关系,非主属性必须直接依赖于主属性,不能间接依赖主属性
2.1、1NF
举例说明三大范式
如下学生信息表(student):
属性 | 含义 |
---|---|
id | 主键 |
name | 姓名 |
sex_code | 性别代号 |
sex_desc | 性别描述 |
contact | 联系方式 |
表内容如下:
id | name | sec_code | sec_desc | contact |
---|---|---|---|---|
001 | 张三 | 0 | 男 | 1783521234_湖北省武汉市xx村 |
002 | 李四 | 0 | 男 | 1783521232_湖北省武汉市xx村 |
003 | 王五 | 1 | 女 | 1783521236_湖北省武汉市xx村 |
如果在查询学生表时经常用到学生的电话号,则应该将联系方式(contact)这一列分为电话号(phone)和地址(address)两列,这样才符合第一范式
id | name | sec_code | sec_desc | phone | contact |
---|---|---|---|---|---|
001 | 张三 | 0 | 男 | 1783521234 | 湖北省武汉市xx村 |
002 | 李四 | 0 | 男 | 1783521232 | 湖北省武汉市xx村 |
003 | 王五 | 1 | 女 | 1783521236 | 湖北省武汉市xx村 |
判断表是否符合第一范式,列是否可以再分,得看需求,如果将电话号和地址分开才能满足查询等需求时,那之前的表设计就是不满足 1NF 的,如果电话号和地址拼接作为一个字段也可以满足查询、存储等需求时,那它就满足 1NF
2.2、2NF
在满足 1NF 的前提下,表中不存在部分依赖,非主键列要完全依赖于主键(主要是说在联合主键的情况下,非主键列不能只依赖于主键的一部分)
如下学生成绩表(score)
CREATE TABLE `score` (
`stu_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '学生id',
`kc_id` int(255) NOT NULL COMMENT '课程id',
`score` int(255) DEFAULT NULL COMMENT '分数',
`kc_name` varchar(255) DEFAULT NULL COMMENT '课程名',
PRIMARY KEY (`stu_id`,`kc_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
stu_id | kc_id | score | kc_name |
---|---|---|---|
001 | 1011 | 85 | 高数 |
001 | 1022 | 79 | 计算机组成原理 |
002 | 1011 | 60 | 高数 |
表中主键为 stu_id 和 kc_id 组成的联合主键。满足1NF;非主键列 score 完全依赖于主键,stu_id 和 kc_id 两个值才能决定 score 的值;而 kc_name 只依赖于 kc_id,与 stu_id 没有依赖关系,它不完全依赖于主键,只依赖于主键的一部分,不符合 2NF
修改使表满足 2NF 后:将原来的成绩表(score)拆分为成绩表(score)和课程表(kc),而且两个表都符合 2NF
成绩表(score)
CREATE TABLE `score` (
`stu_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '学生id',
`kc_id` int(255) NOT NULL COMMENT '课程id',
`score` int(255) DEFAULT NULL COMMENT '分数',
PRIMARY KEY (`stu_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
课程表(kc)
CREATE TABLE `courses` (
`kc_id` int(11) NOT NULL,
`kc_name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`kc_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2.3、3NF
在满足 2NF 的前提下,不存在传递依赖(A -> B, B -> C, A->C)
如下学生信息表(student)
CREATE TABLE `student` (
`id` int(11) NOT NULL COMMENT '主键',
`name` varchar(255) DEFAULT NULL COMMENT '名字',
`sex_code` int(255) DEFAULT NULL COMMENT '性别代号',
`sex_desc` varchar(255) DEFAULT NULL COMMENT '性别描述',
`phone` varchar(255) DEFAULT NULL COMMENT '电话号码',
`address` varchar(255) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
表中 sex_desc 依赖于 sex_code,而 sex_code 依赖于 id(主键),从而推出 sex_desc 依赖于 id(主键);sex_desc 不直接依赖于主键,而是通过依赖于非主键列而依赖于主键,属于传递依赖,不符合 3NF
修改表使满足 3NF 后:
学生表(student)
CREATE TABLE `student` (
`id` int(11) NOT NULL COMMENT '主键',
`name` varchar(255) DEFAULT NULL COMMENT '名字',
`sex_code` int(255) DEFAULT NULL COMMENT '性别代号',
`phone` varchar(255) DEFAULT NULL COMMENT '电话号码',
`address` varchar(255) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
性别表(sexcode)
CREATE TABLE `seccode` (
`sex_code` varchar(255) DEFAULT NULL,
`sex_desc` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
三、三大范式的作用
表的结构更简单、优雅,表的逻辑和条理性更强,并且使用三范式可以很大程度的减少表中的冗余数据,很好的节省了数据库的存储资源
转载请标明出处,原文地址:https://blog.csdn.net/weixin_41835916 如果觉得本文对您有帮助,请点击赞支持一下,您的支持是我写作最大的动力,谢谢。