今日内容–mysql约束
- DQL:查询语句
- 排序查询
- 聚合函数
- 分组查询
- 分页查询
- 约束
- 多表之间的关系
- 范式
- 数据库的备份和还原
学习方法:
mysql这一节属于实操性比较强的知识,内容细而多,必须加强动手练习,才能巩固加强记忆。
一. dql学习
1. 排序查询
-
语法
order by 子句 order by 字段1 排序方式1,字段2 排序方式2,...
注意: 1.排序方式有2种:升序 asc 降序 desc ,默认升序 2.如 字段1 和 字段2 排序有冲突,字段1 优先满足。 3.如字段1数据相同,再按照字段2的排序方式排序。
先建一个表,方便后面查看:
DROP TABLE student;
CREATE TABLE `student` (
`id` INT(11) DEFAULT NULL,
`NAME` VARCHAR(20) DEFAULT NULL,
`age` INT(11) DEFAULT NULL,
`sex` VARCHAR(5) DEFAULT NULL,
`address` VARCHAR(100) DEFAULT NULL,
`math` INT(11) DEFAULT NULL,
`english` INT(11) DEFAULT NULL
) ENGINE=INNODB DEFAULT CHARSET=utf8;
/*Data for the table `student` */
INSERT INTO `student`(`id`,`NAME`,`age`,`sex`,`address`,`math`,`english`) VALUES
(1,'马云',55,'男','杭州',66,78),
(2,'马化腾',45,'女','深圳',98,87),
(3,'马景涛',55,'男','香港',56,77),
(4,'柳岩',20,'女','湖南',76,65),
(5,'柳青',20,'男','湖南',NULL,NULL),
(6,'刘德华',57,'男','香港',99,99),
(7,'马德',22,'女','香港',99,99),
(8,'德玛西亚',18,'男','南京',56,65);
DROP TABLE emp;
CREATE TABLE emp (
id INT(11) DEFAULT NULL,
NAME VARCHAR(20) DEFAULT NULL,
sex CHAR(1) DEFAULT NULL,
age INT(11) DEFAULT NULL,
work_years INT(11) DEFAULT NULL,
birth DATE DEFAULT NULL,
salary DOUBLE(8,2) DEFAULT NULL,
bonus DOUBLE DEFAULT NULL
) ENGINE=INNODB DEFAULT CHARSET=utf8;
/*Data for the table `emp` */
INSERT INTO `emp`(`id`,`name`,`sex`,`age`,`work_years`,`birth`,`salary`,`bonus`) VALUES
(1,'三毛','男',18,1,'2021-01-05',1111.00,500),
(2,'二毛','男',19,2,'2021-01-04',2222.00,600),
(3,'大毛','男',20,3,'2021-01-07',3333.00,700),
(4,'大哥','男',21,3,'2021-01-01',4444.00,800),
(5,'二哥','男',22,2,'2021-01-02',5555.00,900),
(6,'三哥','男',23,1,'2021-01-26',6666.00,100),
(7,'三彪子','男',22,5,'2021-01-02',NULL,200),
(8,'张大彪','男',23,4,'2020-12-01',8888.00,300),
(9,'李云龙','男',30,6,'2020-12-02',9999.00,666),
(10,'楚云飞','男',30,4,'2020-12-05',10000.00,555),
(11,'谢宝庆','男',30,5,'2020-12-04',10040.00,NULL),
(NULL,NULL,'男',28,4,'2020-12-03',10045.00,777),
(13,'金毛狮王','男',60,8,'2020-12-06',20020.00,888),
(14,'紫衫龙王','男',61,9,'2020-12-07',20030.00,999),
(15,'青翼蝠王','男',62,8,'2020-12-08',30000.00,100),
(16,'白眉鹰王','男',63,9,'2020-12-09',40000.00,200),
(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(17,'貂蝉','女',63,9,'2020-12-09',2000,200),
(18,'妲己','女',63,9,'2020-12-09',3000,200),
(19,'金莲','女',63,9,'2020-12-09',4000,200);
-
练习
# 按照数学成绩升序排序,如果数学成绩相同,则按照英语成绩降序排序,如果英语成绩相同,则按照语文成绩升序排序。 select * from stu order by math asc,english desc ,chinese asc;
随堂测试: 1.将员工表emp的员工按照年龄升序排列,在此条件下,工资降序排列
SELECT * FROM emp ORDER BY age ASC ,salary DESC;
2. 聚合函数
-
理解
将一列数据作为一个整体,进行纵向的计算
-
语义
- count 统计个数
- max 求最大值
- min 求最小值
- sum 求和
- avg 求平均值
-
注意
1.聚合函数统计时会排序null值,即不统计字段为null 的记录 2.可以使用ifnull() 解决
-
练习
1.统计班级共用多少学员 2.统计数学成绩的最大值 3.统计英语成绩的最小值 4.求班级英语成绩总和 5.求班级英语成绩和数学成绩相加的总和 6.求班级数学成绩的平均数
SELECT COUNT(*)FROM student ;-- 8 1.统计班级共用多少学员
SELECT COUNT(english)FROM student ;-- 7
SELECT COUNT(IFNULL(english,0))FROM student ;-- 8
SELECT MAX(math) FROM student;-- 99 2.统计数学成绩的最大值
SELECT MIN(english) FROM student;-- 65 3.统计英语成绩的最小值
SELECT MIN(IFNULL(english,0)) FROM student;-- 0
SELECT SUM(english) FROM student;-- 570 4.求班级英语成绩总和
SELECT SUM(english)+SUM(math) FROM student;-- 1120 5.求班级英语成绩和数学成绩相加的总和
SELECT AVG(math) FROM student;-- 78.5714 6.求班级数学成绩的平均数
-
补充
count(*) 和 count(列名)的区别: 1.count(*)不会排除null,意为:统计所有的记录数,哪怕某一行所有的列都是null,也会统计在内 2.count(列名)会排除null,意为:统计某一列不为null的记录数 3.count(数字)和count(*)等效
随堂测试:
1.查询员工表中工资的平均值
2.查询员工表中工资大于平均工资的员工的信息
3.查询员工表中年龄最大的人的信息
4.查询公司每个月要发多少工资(工资+津贴)
SELECT AVG(salary) FROM emp;-- 10630.722 1.查询员工表中工资的平均值
SELECT * FROM emp WHERE salary>(SELECT AVG(salary) FROM emp);-- 2.查询员工表中工资大于平均工资的员工的信息
SELECT * FROM emp WHERE age=(SELECT MAX(age) FROM emp);-- 63 3.查询员工表中年龄最大的人的信息
SELECT SUM(salary)+SUM(bonus) FROM emp;-- 200238 4.查询公司每个月要发多少工资(工资+津贴)
-- 请思考以下两种求和方式有何细致区别:
SELECT SUM(salary)+SUM(bonus) FROM emp
SELECT SUM(salary+bonus) FROM emp
/*
结论:
同一行数据,和null值横向相加,结果还是null
同一列数据,和null值纵向相加,null会当作0
*/
-- 正确的方式
SELECT SUM(IFNULL(salary,0)+IFNULL(bonus,0)) FROM emp
-- 或
SELECT SUM(salary)+SUM(bonus) FROM emp
3. 分组查询
-
理解分组:统计具有相同特征的某一类数据
-
语法
group by 字段
-
注意
1.分组查询中,select后面只能出现 分组的字段和聚合函数,不能出现其它字段,否则没有意义
随堂测试: 1.查询公司所有女性员工的总工资 2.查询财务部的平均工资 注意两点: 1.相同特征作为分组依据,如:女性,财务部 2.查询的对象需匹配整个群体的特征,如:总工资,平均工资 请说明如下查询语义是否正确,如不正确该如何更正: 1.查询公司所有女性员工的年龄 2.查询财务部的员工姓名
SELECT SUM(salary) FROM emp WHERE sex='女';-- 9000 1.查询公司所有女性员工的总工资
SELECT SUM(salary),sex FROM emp GROUP BY sex;
ALTER TABLE emp ADD dept VARCHAR(20);-- 添加列,并进行修改
UPDATE emp SET dept='财务' WHERE id BETWEEN 1 AND 16;
UPDATE emp SET dept='前台' WHERE id BETWEEN 17 AND 19;
SELECT AVG(salary),dept FROM emp WHERE dept='财务';-- 12307.714286
SELECT AVG(salary),dept FROM emp GROUP BY dept HAVING dept='财务';-- 12307.714286
-
分组前条件 和 分组后条件 过滤结果集
- where 分组前条件
- having 分组后条件
-
注意:
1.where 在分组前进行条件过滤,不满足条件的记录不参与分组,不能跟 聚合函数 2.having 在分组后进行条件限定,不满足限定的记录不会被查询出来, 可以跟 聚合函数
-
案例
-- 1.按照性别分组,分别查询男女同学的数学平均分,人数 select sex ,avg(math),count(id) from stu group by sex; -- 2.按照性别分组,分别查询男女同学的数学平均分,人数;要求分数低于70的人,不参与分组 select sex ,avg(math),count(id) from stu where math>=70 group by sex; -- 3.按照性别分组,分别查询男女同学的数学平均分,人数;要求分数低于70的人,不参与分组;分组后的人数要大于2人 select sex ,avg(math),count(id) from stu where math>=70 group by sex having count(id)>2; -- 使用别名 select sex ,avg(math),count(id) 人数 from stu where math>=70 group by sex having 人数>2;
-
课堂提问:执行如下 SQL 语句,运行结果是?
select sex,sum(math) from stu group by sex where sum(math) > 30; -- 运行错误,group by 后面不能出现 where ,应使用having
随堂测试: 1.公司决定组织一次海外旅游,只有工资高于3000的员工才能参加,请统计出每个部门的参加人数。 2.为节省经费,只有可参加人数小于3的部门才能去旅游。
SELECT dept,COUNT(id) FROM emp WHERE salary>3000 GROUP BY dept;
SELECT dept,COUNT(id) FROM emp WHERE salary>3000 GROUP BY dept HAVING COUNT(id)<3;
4. 分页查询
-
引出分页
数据库中有大量符合搜索条件的数据,但是我们没有必要一次性全部展示,一来查询耗时,二来网络传输耗时,因此我们使用分页展示。
-
语法
limit offset,size -- offset 起始行数,从 0 开始计数,如果省略,默认就是 0 -- size 每页展示的记录数
-
案例和公式
-- 每页展示三条学生记录,查询第一页 select * from stu limit 0,3 -- 查询第二页 select * from stu limit 3,3 -- 查询第三页 select * from stu limit 6,3
公式–找出当前页数和起始行数之间的规律
起始行数 start=(currPage-1)*size - currPage 当前页数 - size 每页展示的记录数 注意:limit 语法是mysql的方言,其它数据库,对于分页有不同的实现方式。
随堂测试:
1.查询员工表的第2页数据,每页展示3条数据
SELECT * FROM emp LIMIT 3,3;
二. 约束
-
概念:
对表中的数据进行限定,从而保证数据的正确性,有效性,完整性。
-
分类:
1.主键约束:primary key 2.非空约束:not null 3.唯一约束:unique 4.外键约束:foreign key
1. 非空约束
-
语法
not null
-
使用
1.在创建表时添加约束
create table stu( id int, name varchar(20) not null );
-
删除非空约束
alter table stu modify name varchar(20);
2.创建表之后,添加约束
alter table stu modify name varchar(20) not null;
-
2. 唯一约束
-
语法
unique -- 某一列的值不能重复
-
使用
-- 1.创建表时添加唯一约束 create table stu ( id int, phone_number varchar(20) unique ); -- 2.删除唯一约束 alter table stu modify phone_number varchar(20); -- 错误写法,不会真的删除 alter table stu drop index phone_number; -- 删除phone_number的索引 -- 3.创建表完成后,添加唯一约束 alter table stu modify phone_number varchar(20) unique;
-
补充:
index索引: 1.一张表的索引可以看成是一本书的目录,添加索引可以提高查找效率。 2.索引就是一张小表,用于存储某列值的地址值 3.一张表中索引太多反而会增加查询工作量,延长时间,降低效率 4.我们可以定义这个索引具有唯一性,所以唯一约束是通过索引index来实现的。
3.主键约束
注意
1.主键含义:非空 且 唯一
2.一张表只能有一个字段为主键
3.主键就是表中记录的唯一标识
-
补充:
1.主键是一种特殊的唯一索引 2.主键列不允许空值,而唯一性索引列允许空值
-
使用
-- 1.在创建表时添加主键 create table stu( id int primary key, name varchar(20) ); -- 2.删除主键 alter table stu modify id int;-- 错误写法,不会真的删除主键 alter table stu drop primary key; -- 删除主键,无需指定列,因为一个表只有一个列可以设为主键 -- 3.创建完表后,添加主键 alter table stu modify id int primary key;
3.1 主键约束–自增长
-
概念:如果某一列是数值类型,使用auto_increment 可以完成值的自动增长c
-
使用
-- 1.创建表时,设置主键自增长,默认从1开始自增长 create table stu( id int primary key auto_increment, name varchar(20) ); -- 2.创建表时,设置主键自增长,并指定自增长起始值为6 create table stu( id int primary key auto_increment, name varchar(20) )auto_increment=6; -- 3.删除自增长,不会删除主键 alter table stu modify id int; -- 4.创建表完成后,添加自增长 ALTER TABLE stu MODIFY id INT AUTO_INCREMENT;-- 注意:此次不能再指定主键,因为主键已经存在 -- 5.创建表完成后,设置主键自增长的初始值--前提是表中已经设定过主键自增长 ALTER TABLE stu AUTO_INCREMENT=100;
4. 外键约束
-
创建员工部门表,记录员工的详细信息
-- 创建员工部门表 create table emp_dept( id int primary key auto_increment, name varchar(20) not null, age int , dept_name varchar(20),-- 所属公司部门名称 dept_loc varchar(20) -- 所属公司部门地址 ); -- 插入数据 insert into emp_dept values(null,'张三',18,'研发部','广州'); insert into emp_dept values(null,'李四',19,'研发部','广州'); insert into emp_dept values(null,'王五',20,'研发部','广州'); insert into emp_dept values(null,'大王',21,'销售部','武汉'); insert into emp_dept values(null,'小王',22,'销售部','武汉'); insert into emp_dept values(null,'王炸',23,'销售部','武汉');
-
观察数据发现问题:存在数据冗余。解决办法:拆分成两个表
-- 先删除员工部门表 drop table emp_dept; -- 创建部门表 create table dept ( id int primary key auto_increment, dept_name varchar(20), dept_loc varchar(20) ); -- 创建员工表 create table emp( id int primary key auto_increment, name varchar(20) not null, age int , dept_id int ); -- 插入dept表数据 insert into dept values(null,'研发部','广州'); insert into dept values(null,'销售部','武汉'); -- 插入emp表数据 insert into emp values(null,'张三',18,1); insert into emp values(null,'李四',19,1); insert into emp values(null,'王五',20,1); insert into emp values(null,'大王',21,2); insert into emp values(null,'小王',22,2); insert into emp values(null,'王炸',23,2);
-
操作数据发现问题:
- 删除部门表数据,会造成员工表中相对应的数据失去意义
- 添加新员工时,可以随意填写不存在的部门编号
-
实际情况:
- 公司要解散某个部门,必须先安排好该部门的所有员工
- 公司要组建一个新部门,也要先成立部门,再招员工
-
解决办法:
- 添加外键约束–关联两个表
-- 删除员工表 drop table emp; -- 重新创建员工表 create table emp( id int primary key auto_increment, name varchar(20) not null, age int, dept_id int , constraint emp_dept_fk foreign key(dept_id) references dept(id) ); -- 插入emp表数据 insert into emp values(null,'张三',18,1); insert into emp values(null,'李四',19,1); insert into emp values(null,'王五',20,1); insert into emp values(null,'大王',21,2); insert into emp values(null,'小王',22,2); insert into emp values(null,'王炸',23,2);
-
删除外键
alter table emp drop foreign key emp_dept_fk;-- 更改表,删除外键emp_dept_fk
-
创建表之后,添加外键
alter table emp add constraint emp_dept_fk foreign key (dept_id) references dept(id);
4.1 外键约束–级联操作
-
提出问题:如何将部门表dept中的部门编号1修改为5
-- 1.先把员工表中的dept_id 修改为 null update emp set dept_id =null where dept_id=1; -- 2.再手动修改部门编号为5 -- 3.将员工表中的dept_id 修改为5 update emp set dept_id=5 where dept_id is null;
-
有更简单的实现吗?-- 在设置外键时,设置级联操作
-
查看 架构设计图
-
级联修改
-- 先删除外键 alter table emp drop foreign key emp_dept_fk;-- 更改表,删除外键emp_dept_fk -- 重新添加外键,并设置级联修改--末尾追加 on update cascade alter table emp add constraint emp_dept_fk foreign key (dept_id) references dept(id) on update cascade;
-
级联删除
-- 先删除外键 alter table emp drop foreign key emp_dept_fk;-- 更改表,删除外键emp_dept_fk -- 重新添加外键,并设置级联修改和级联删除 alter table emp add constraint emp_dept_fk foreign key (dept_id) references dept(id) on update cascade on delete cascade;
-
-
补充
1.级联更新和级联删除可以一起使用,也可以单个使用,级联删除需要谨慎使用 2.级联的理解:单向--> 父表在更新或者删除时,更新或者删除子表对应记录
三. 多表关系介绍
- 数据库设计
- 表与表之间的对应关系
- 一对一
- 人和身份证
- 一对多
- 员工和部门
- 多对多
- 学生和课程
- 一对一
- 数据库设计的范式
- 表与表之间的对应关系
1. 一对多关系实现
- 在多的一方建立外键指向一的一方的主键
2. 多对多关系实现
- 多对多关系实现需要借助第三方中间表,该表至少包含两个字段。这两个字段作为第三张表的外键,分别指向两张表的主键。
3. 一对一
- 一对一关系实现:可以在任意一方添加唯一外键指向另一方的主键
4. 案例
-
一对多关系案例
- 需求:一个旅游线路分类中有多个旅游线路
-- 创建旅游线路分类表 tab_category create table tab_category ( cid int primary key auto_increment,-- 旅游线路分类主键 cname varchar(100) not null unique -- 旅游线路分类名称 ); -- 插入数据 insert into tab_category (cname) values ('周边游'), ('出境游'), ('国内游'), ('港澳游'); -- 创建旅游线路表 tab_route create table tab_route( rid int primary key auto_increment, -- 旅游线路主键 rname varchar(100) not null unique,-- 旅游线路名称 price double, -- 价格 rdate date, -- 上架时间 cid int, -- cid 外键 foreign key (cid) references tab_category(cid) ); -- 添加旅游线路数据 INSERT INTO tab_route VALUES (NULL, '【厦门+鼓浪屿+南普陀寺+曾厝垵 高铁 3 天 惠贵团】尝味友鸭面线 住 1 晚鼓浪屿', 1499, '2018-01-27', 1), (NULL, '【浪漫桂林 阳朔西街高铁 3 天纯玩 高级团】城徽象鼻山 兴坪漓江 西山公园', 699, '2018-02- 22', 3), (NULL, '【爆款¥1699 秒杀】泰国 曼谷 芭堤雅 金沙岛 杜拉拉水上市场 双飞六天【含送签费 泰风情 广州 往返 特价团】', 1699, '2018-01-27', 2), (NULL, '【经典•狮航 ¥2399 秒杀】巴厘岛双飞五天 抵玩【广州往返 特价团】', 2399, '2017-12-23', 2), (NULL, '香港迪士尼乐园自由行 2 天【永东跨境巴士广东至迪士尼去程交通+迪士尼一日门票+香港如心海景酒店 暨会议中心标准房 1 晚住宿】', 799, '2018-04-10', 4);
-
多对多关系案例
-- 创建用户表 tab_user create table tab_user ( uid int primary key auto_increment,-- 主键 username varchar(100) unique not null,-- 用户名 password varchar(30) not null,-- 密码 name varchar(100),-- 用户姓名 birthday date,-- 生日 sex char(1) default '男',-- 性别 telephone varchar(11),-- 手机 email varchar(100)-- 邮箱 ); -- 添加用户数据 INSERT INTO tab_user VALUES (NULL, 'cz110', 123456, '老王', '1977-07-07', '男', '13888888888', '66666@qq.com'), (NULL, 'cz119', 654321, '小王', '1999-09-09', '男', '13999999999', '99999@qq.com'); -- 创建收藏表 tab_favorite create table tab_favorite ( rid int, date datetime, uid int, primary key(rid,uid),-- 创建复合主键 foreign key (rid) references tab_route(rid), foreign key(uid) references tab_user(uid) ); -- 增加收藏表数据 INSERT INTO tab_favorite VALUES (1, '2018-01-01', 1), -- 老王选择厦门 (2, '2018-02-11', 1), -- 老王选择桂林 (3, '2018-03-21', 1), -- 老王选择泰国 (2, '2018-04-21', 2), -- 小王选择桂林 (3, '2018-05-08', 2), -- 小王选择泰国 (5, '2018-06-02', 2); -- 小王选择迪士尼
四. 范式
1. 概述
1.什么是范式:
制定一些规则来优化数据的设计和存储,这些规则就称为范式。
2.三大范式:
目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)
满足最低要求的范式是第一范式(1NF)。在第一范式的基础上进一步满足更多规范要求的称为第二范式(2NF) ,其余范式以次类推。一般说来,数据库只需满足第三范式(3NF)就行了。
1NF:
第一范式每一列不可再拆分,称为原子性。
2NF:
第二范式就是在第一范式的基础上所有列完全依赖于主键列。
当存在一个复合主键包含多个主键列的时候,才会发生不符合第二范式的情况。
比如有一个主键有两个列,不能存在这样的属性,它只依赖于其中一个列,这就是不符合第二范式。
第二范式的特点:
1) 一张表只描述一件事情。
2) 表中的每一列都完全依赖于主键
3NF:
第三范式就是所有列不依赖于其它非主键列,也就是在满足 2NF 的基础上,任何非主列不得传递依赖于主键。
2. 三大范式详解
-
创建最开始的表
-- 创建学员相关信息表 create table stu( id varchar(10), name varchar(10), major varchar(20),-- 系名和系主任 course varchar(20),-- 课程 score int -- 分数 ); -- 插入数据 insert into stu values ('10010','张无忌','经济系 张三丰','高等数学',95), ('10010','张无忌','经济系 张三丰','大学英语',87), ('10010','张无忌','经济系 张三丰','计算机基础',65), ('10011','令狐冲','法律系 任我行','法理学',77), ('10011','令狐冲','法律系 任我行','大学英语',87), ('10011','令狐冲','法律系 任我行','法律社会学',65), ('10012','杨过','经济系 张三丰','法律社会学',95), ('10012','杨过','经济系 张三丰','法理学',97), ('10012','杨过','经济系 张三丰','大学英语',99);
这样建表存在的问题: 1.如果更改系主任,需要更改整个系的信息,数据没有独立 2.存在大量数据冗余 3.新增一个系的信息时,其它字段数据为空,造成数据不完整 4.学员毕业,删除一个学员信息时,会连带删除系的信息
-
使用第一范式,优化表结构
-- 删除表 drop table stu; -- 创建学员相关信息表,拆分系名和系主任为两个字段 create table stu( id varchar(10), name varchar(10), major_name varchar(20),-- 系名 major_monitor varchar(20),-- 系主任 course varchar(20),-- 课程名 score int -- 分数 ); -- 插入数据 insert into stu values ('10010','张无忌','经济系','张三丰','高等数学',95), ('10010','张无忌','经济系','张三丰','大学英语',87), ('10010','张无忌','经济系','张三丰','计算机基础',65), ('10011','令狐冲','法律系','任我行','法理学',77), ('10011','令狐冲','法律系','任我行','大学英语',87), ('10011','令狐冲','法律系','任我行','法律社会学',65), ('10012','杨过','经济系','张三丰','法律社会学',95), ('10012','杨过','经济系','张三丰','法理学',97), ('10012','杨过','经济系','张三丰','大学英语',99);
-
存在非完全依赖
- 分数的唯一确定,需要依赖学号和课程,所以,如果以学号和课程作为核心字段的话,我们发现姓名和系名以及系主任的确定,只跟学号有关,和课程无关,这就说明存在非完全依赖。
-
按照第二范式优化表结构,去除非完全依赖
-- 拆分为 学员 和 考试成绩 两个表 create table stu( id varchar(10),-- 学员编号 name varchar(20), -- 学员姓名 major_name varchar(20), -- 系名 major_monitor varchar(20) -- 系主任 ); create table exam( id varchar(10),-- 学员编号 course varchar(10),-- 课程名 score int -- 分数 ); -- 插入数据 insert into stu values ('10010','张无忌','经济系','张三丰'), ('10010','张无忌','经济系','张三丰'), ('10010','张无忌','经济系','张三丰'), ('10011','令狐冲','法律系','任我行'), ('10011','令狐冲','法律系','任我行'), ('10011','令狐冲','法律系','任我行'), ('10012','杨过','经济系','张三丰'), ('10012','杨过','经济系','张三丰'), ('10012','杨过','经济系','张三丰'); insert into exam values ('10010','高等数学',95), ('10010','大学英语',87), ('10010','计算机基础',65), ('10011','法理学',77), ('10011','大学英语',87), ('10011','法律社会学',65), ('10012','法律社会学',95), ('10012','法理学',97), ('10012','大学英语',99);
-
观察数据发现,学员表中存在传递依赖
- 学员姓名可以确定系名,系名可以确定系主任,学员姓名也可以直接确定系主任,此关系为传递依赖
- 存在传递依赖,说明表结构还不够单一化,还不够简洁,并且还存在数据冗余
-
按照第三范式的要求,消除传递依赖,进一步优化表结构,继续拆分表
-- 先删除学员表 drop table stu; -- 拆分学员表为 学员表和系表 create table stu( id varchar(10) primary key,-- 学员编号 此时方可添加主键 name varchar(20) -- 学员姓名 ); create table major( major_name varchar(20) primary key, -- 系名 major_monitor varchar(20) -- 系主任 ); -- 插入数据 insert into stu values ('10010','张无忌'), ('10011','令狐冲'), ('10012','杨过'); insert into major values ('经济系','张三丰'), ('法律系','任我行');
-
总结:
范式 特点 1NF 原子性:表中每列不可再拆分。 2NF 不产生局部依赖,一张表只描述一件事情 3NF 不产生传递依赖,表中每一列都直接依赖于主键。而不是通过其它列间接依赖于主键。 设计范式的目的: 1.使结构更合理,使数据冗余尽量小。便于插入、删除和更新 2.遵从概念单一化“一事一地”原则,即一个关系模式描述一个实体或实体间的一种联系。 3.范式的实质就是概念的单一化
五. 数据库的备份和还原
-
命令行操作
-- 备份 mysqldump -u用户名 -p密码 备份的数据库名 > 保存的sql文件路径 -- 练习:备份数据库db1 mysqldump -uroot -proot db1 > f:/a.sql
-- 还原 ,需要登录后操作 -- 1.创建数据库 create database db1; -- 2.使用数据库 use db1; -- 3.导入sql文件 source f:/a.sql;
步骤:
win+R cmd
– 备份
– 还原 ,需要登录后操作
– 1.创建数据库
– 2.使用数据库
– 3.导入sql文件
- 可视化工具操作