Loading... # 今日内容 1. DQL:查询语句的使用 1. 排序查询 2. 聚合函数 3. 分组查询 4. 分页查询 2. 约束 1. 概述 2. 非空约束 3. 唯一约束 4. 主键约束 5. 自动增长 6. 外键约束 7. 级联操作 3. 多表之间的关系 4. 范式 5. 数据库的备份与还原 # DQL:查询语句 给出初始数据 ```sql CREATE TABLE student ( id int, -- 编号 name varchar(20), -- 姓名 age int, -- 年龄 sex varchar(5), -- 性别 address varchar(100), -- 地址 math int, -- 数学 english int -- 英语 ); 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,'男','湖南',86,NULL), (6,'刘德华',57,'男','香港',99,99), (7,'马德',22,'女','香港',99,99), (8,'德玛西亚',18,'男','南京',56,65); select * from student; ``` ![图1](https://blog.fivk.cn/usr/uploads/2021/12/1102236746.png) ## 1.排序查询 - 语法:`order by 子句` - order by 排序字段1 排序方式1, 排序字段2 排序方式2 - 排序方式: - `ASC`:升序排序(默认) - `DESC`:降序排序 - 注意如果有多个排序条件,则当前边的条件值一样时,才会判断第二条件。 ### 1.按照数学成绩排序 - 升序排序: ```sql select * from student order by math; ``` ```sql select * from student order by math asc; ``` 这两个语法都是按照`ASC`降序排序。 ![图2](https://blog.fivk.cn/usr/uploads/2021/12/1917708720.png) - 降序排序: ```sql select * from student order by math desc; ``` 此语法使用`DESC`降序排序。 ![图3](https://blog.fivk.cn/usr/uploads/2021/12/3770033468.png) ### 2.如果数学成绩一样,则按照英语成绩排序 ```sql select * from student order by math desc, english desc; ``` 用`,`隔开,表示多个权重排序,只有当前面权重大的条件排序相同时才根据权重小的条件排序。 ![图4](https://blog.fivk.cn/usr/uploads/2021/12/3708499733.png) ## 2.聚合函数 <div class="tip inlineBlock info"> 将一列数据作为整体,进行**纵向**的计算。 </div> 其实很好理解,就是比如我们要计算数学成绩的平均分,就需要用到聚合。 - `COUNT`:计算个数 - 一般选择主键(保证非空,或则 选择*) - `MAX`:计算最大值 - `MIN`:计算最小值 - `SUM`:计算求和 - `AVG`:计算平均值 <div class="tip inlineBlock warning"> 注意:聚合函数的计算它会排除`NULL`值 </div> <div class="tip inlineBlock success"> 解决方法: 1. 选择不包含非空的列进行计算(主键等) 2. `IFNULL`函数 </div> ### 1.查询有多少个人 ```sql select count(id) from student; ``` 这一行代码返回8,这个单元表。 ### 2.排除NULL被排除情况 ```sql select count(english) from student ``` 这个查询结果为7,因为存在`english`的值为`NULL`的情况。 我们如何解决呢? - 方法1: ```sql select count(ifnull(english,0)) from student ``` 我们可以用`IFNULL`将`NULL`替换为`0`,查询结果就为`8`。 - 方法2: 选择非空的列。 ### 3.求数学绩的最高分、最低分、平均分、总分 - 最高分 ```sql select max(math) from student; ``` - 最低分 ```sql select min(math) from student; ``` - 平均分 ```sql select avg(math) from student; ``` - 总分 ```sql select sum(math) from student; ``` <div class="tip inlineBlock warning"> 这几个运行结果就不展示了。 </div> ## 3.分组查询 <div class="tip inlineBlock info"> 分组查询是指使用 `GROUP BY` 语句对查询信息进行分组,相同数据作为一组。 </div> **语法:** ```sql select 字段 1,字段 2... from 表名 group by 分组字段 [having 条件]; ``` 注意: 1. 分组之后查询的字段只能是:分组字段、聚合函数 2. `WHERE`和`HVAING`的区别 1. `WHERE`:在分组之前进行限定,如果不满足条件,则不参与分组 2. `HAVING`:在分组之后进行限定,如果不满足条件,则不会被查询出来 3. `WHERE`后不能跟聚合函数,`HAVING`可以进行聚合函数判断。 ### 1.按照性别分组分别查询男、女同学的平均分以及人数 ```sql select sex, avg(math), count(id) from student group by sex; ``` ![图5](https://blog.fivk.cn/usr/uploads/2021/12/1377402603.png) <div class="tip inlineBlock info"> 分组之后查询的字段只能是:分组字段、聚合函数 </div> 这里`sex`是分组字段,`ave`、`count`是聚合函数。因为,既然分组了,就只能看一个整体,不能看单独的某条记录的字段。 - 如果加入了不是分组字段也不是聚合函数,比如加入了`name`,运行的结果中`name`没有任何的意义。 ### 2.同样查询男女平均分但是要求“分数低于70的人不参与分组” ```sql select sex, avg(math), count(id) from student where math >=70 group by sex; ``` ![图6](https://blog.fivk.cn/usr/uploads/2021/12/2440739159.png) ### 3.去除低于70分的分组后,再要求统计人数要大于2人 <div class="tip inlineBlock success"> 这里我们引入`HAVING`关键字,对分组查询的结果通过返回的分组字段、聚合函数再进行过滤。 </div> ```sql select sex, avg(math), count(id) from student where math >=70 group by sex having count(id) > 2; ``` ## 4.分页查询 **语法:** ```sql limit offset, length ``` | 参数 | 作用 | | -------- | -------------------------------------------- | | offset | 起始行数,从0开始计数,如果省略,默认就是0 | | length | 返回的行数 | ```sql select 字段列表 [as 别名]from 表名 [where 子句] [group by 子句][having 子句][order by 子句][limit 子句]; ``` <div class="tip inlineBlock info"> LIMIT 是限制的意思,所以 LIMIT 的作用就是限制查询记录的条数。 </div> ### 每页显示三条记录 - 第一页: ```sql select * from student limit 0,3 ``` ![图7](https://blog.fivk.cn/usr/uploads/2021/12/2526664051.png) - 第二页: ```sql select * from student limit 3,3 ``` ![图7](https://blog.fivk.cn/usr/uploads/2021/12/1929907215.png) **分页公式:** $offset = (当前的页码 - 1) * length$ <div class="tip inlineBlock share"> `limit`作是一个“方言”,每种sql语言分页的使用方法都有一定的差异。 </div> # 约束 **约束的作用:** <div class="tip inlineBlock info"> 对表中的数据进行限制,保证数据的正确性、有效性和完整性。一个表如果添加了约束,不正确的数据将无 法插入到表中。约束在创建表的时候添加比较合适。 </div> **约束种类:** | 约束名 | 约束关键字 | | ---------- | ----------------------- | | 主键约束 | primary key | | 唯一约束 | unique | | 非空约束 | ont null | | 外键约束 | foreign key | | 检查约束 | check 注:MySQL不支持 | ## 1.非空约束:not null <div class="tip inlineBlock success"> 概念:某一列不能为 null。 </div> ### 1.创建表时给name添加约束 ```sql create table stu ( id int, name varchar(32) not null -- name 为非空约束 ); ``` ### 2.删除name的非空约束 ```sql alter table stu modify name varchar(32); ``` ### 3.在创建表之后添加非空约束 ```sql alter table stu modify name varchar(32) not null; ``` ## 2.唯一约束unique <div class="tip inlineBlock success"> 概念:表中某一列不能出现重复的值。 </div> 注意: 1. 唯一约束可以有`null`,但是只能有一列一条(唯一约束)。 ### 1.在创建表示添加唯一约束 ```sql create table stu( id int; phone_number varchar(32) unique -- 手机号只能是唯一的 ); ``` 此时,`phone_number`的值不能有重复的。 <div class="tip inlineBlock info"> 唯一约束可以有`null`,但是只能有一列一条(唯一约束了) </div> ### 2.删除表中的唯一约束 ```sql alter table stu drop index phone_number; ``` ### 3.在表创建完后添加唯一约束 ```sql alter table stu modify phone_number varchar(32) unique; ``` <div class="tip inlineBlock info"> 添加唯一约束前,需要保证此列没有重复值。 </div> ## 3.主键约束 primary key <div class="tip inlineBlock success"> 概念:用来唯一标识数据库中的每一条记录。 含义:非空且唯一 </div> 注意: 1. 含义是非空且唯一 2. 一张表只能有一个字段为主键 3. 主键就是表中记录的唯一标识 ### 在创建表时添加主键约束 ```sql create table stu( id int primary key, -- 给id添加了主键约束 name varchar(20) ); ``` ### 删除主键 ```sql alter table stu drop primary key; ``` <div class="tip inlineBlock warning"> 为什么没有去指定删除哪一个字段主键呢? </div> <div class="tip inlineBlock success"> 因为表中只有这唯一的一个字段。 </div> ### 创建完表后添加主键 ```sql alter table stu modify id int primary key; ``` ### 自动增长 <div class="tip inlineBlock success"> 概念:主键如果让我们自己添加很有可能重复,我们通常希望在每次插入新记录时,数据库自动生成主键字段的值。 关键字:`AUTO_INCREMENT` 表示自动增长(字段类型必须是整数类型) </div> - 自动增长可以不和主键一起,其他键都行。 #### 创建表时添加主键约束并且完成自增长 ```sql create table stu( id int primary key auto_increment, -- 给id添加主键约束并完成自增长 name varchar(20) ); ``` 此时,插入记录时,可以不填主键,它会自动在原有基础上完成自增长。 #### 创建表后添主键自动增长 ```sql alter table stu modify id int auto_increment; ``` #### 取消主键自动增长 ```sql alter table stu modify id int; ``` ## 4.外键约束 <div class="tip inlineBlock success"> 概念:让表与表产生关系,从而保证数据的正确性。 </div> 语法: - 新建表时增加外键: ```sql [CONSTRAINT] [外键约束名称] FOREIGN KEY(外键字段名) REFERENCES 主表名(主键字段名) ``` - 已有表增加外键: ```sql ALTER TABLE 从表 ADD [CONSTRAINT] [外键约束名称] FOREIGN KEY (外键字段名) REFERENCES 主表(主键字段名); ``` 先准备数据: ```sql CREATE TABLE emp ( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(30), age INT, dep_name VARCHAR(30), -- 部门名称 dep_location VARCHAR(30) -- 部门地址 ); -- 添加数据 INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('张三', 20, '研发部', '广州'); INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('李四', 21, '研发部', '广州'); INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('王五', 20, '研发部', '广州'); INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('老王', 20, '销售部', '深圳'); INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('大王', 22, '销售部', '深圳'); INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('小王', 18, '销售部', '深圳'); select * from emp; ``` ![图8](https://blog.fivk.cn/usr/uploads/2021/12/3901164520.png) <div class="tip inlineBlock info"> 我们发现,研发部只广州,销售部只对应深圳。所以存在了数据冗余。 所以我们不用这个数据。 </div> <div class="tip inlineBlock share"> 外键可以为`NULL`但是不能为不存在的值。 </div> ### 解决冗余方法 <div class="tip inlineBlock success"> 解决方案:分成 2 张表 </div> - 创建部门表(id,dep_name,dep_location) 一方,主表 ```sql create table department( id int primary key auto_increment, dep_name varchar(20), dep_location varchar(20) ); ``` - 创建员工表(id,name,age,dep_id) 多方,从表 ```sql create table employee( id int primary key auto_increment, name varchar(20), age int, dep_id int -- 外键对应主表的主键 ); ``` 添加 2 个部门 ```sql insert into department values(null, '研发部','广州'),(null, '销售部', '深圳'); select * from department; ``` ![图9](https://blog.fivk.cn/usr/uploads/2021/12/1055323347.png) 添加员工,dep_id 表示员工所在的部门 ```sql INSERT INTO employee (NAME, age, dep_id) VALUES ('张三', 20, 1); INSERT INTO employee (NAME, age, dep_id) VALUES ('李四', 21, 1); INSERT INTO employee (NAME, age, dep_id) VALUES ('王五', 20, 1); INSERT INTO employee (NAME, age, dep_id) VALUES ('老王', 20, 2); INSERT INTO employee (NAME, age, dep_id) VALUES ('大王', 22, 2); INSERT INTO employee (NAME, age, dep_id) VALUES ('小王', 18, 2); select * from employee; ``` ![图10](https://blog.fivk.cn/usr/uploads/2021/12/1887195280.png) <div class="tip inlineBlock success"> 我们现在就得到了,**部门表**和**员工表**。 </div> ### 新建表时增加外键 **格式:** ```sql create table 表名( ..., 外键列 constraint 外键名称 foreign key 外键列名称 reference 主表名称(主列列名名称) ); ``` 如果刚创建了`department`和`employee` 这两个表,那么现在先删除,我们重新创建。 ```sql drop table department; drop table employee; ``` <div class="tip inlineBlock warning"> 现在我们重新创建`employee`表,让`employee`中的`dep_id`关联`department`中的`id`。 </div> - 先要有部门表 ```sql create table department( id int primary key auto_increment, dep_name varchar(20), dep_location varchar(20) ); ``` - 然后员工表关联部门 ```sql create table employee( id int primary key auto_increment, name varchar(20), age int, dep_id int, -- 外键对应主表的主键 constraint emp_dept_id foreign key (dep_id) references department(id) ); ``` <div class="tip inlineBlock info"> 我们在最后加入了一行语句,记得前面要有逗号分隔。 </div> - 加入数据 ```sql insert into department values(null, '研发部','广州'),(null, '销售部', '深圳'); INSERT INTO employee (NAME, age, dep_id) VALUES ('张三', 20, 1); INSERT INTO employee (NAME, age, dep_id) VALUES ('李四', 21, 1); INSERT INTO employee (NAME, age, dep_id) VALUES ('王五', 20, 1); INSERT INTO employee (NAME, age, dep_id) VALUES ('老王', 20, 2); INSERT INTO employee (NAME, age, dep_id) VALUES ('大王', 22, 2); INSERT INTO employee (NAME, age, dep_id) VALUES ('小王', 18, 2); ``` - 可以分别查看两个表 <div class='album_block'> [album type="photos"] ![](https://blog.fivk.cn/usr/uploads/2021/12/1055323347.png) ![](https://blog.fivk.cn/usr/uploads/2021/12/1887195280.png) [/album] </div> 现在就是外键关联的表,我们删除`department`表时,就不能直接删除,必须要将所关联的员工先删除。 ### 删除外键约束 **格式:** ```sql ALTER TABLE 从表 drop foreign key 外键名称; ``` **案例:** ```sql alter table employee drop foreign key emp_dept_id; ``` ### 已有表增加外键 **格式:** ```sql ALTER TABLE 从表 ADD [CONSTRAINT] [外键约束名称] FOREIGN KEY (外键字段名) REFERENCES 主表(主键字段名); ``` **案例:** ```sql alter table employee add constraint emp_dept_id foreign key (dep_id) references department(id); ``` ### 级联操作 - 作用? - 出现新的问题: ```sql select * from employee; select * from department; -- 要把部门表中的 id 值 2,改成 5,能不能直接更新呢? -- Cannot delete or update a parent row: a foreign key constraint fails update department set id=5 where id=2; -- 要删除部门 id 等于 1 的部门, 能不能直接删除呢? -- Cannot delete or update a parent row: a foreign key constraint fails delete from department where id=1; ``` <div class="tip inlineBlock info"> 这就需要用到我们的级联操作了。 </div> <div class="tip inlineBlock success"> 概念:在修改和删除主表的主键时,同时更新或删除副表的外键值,称为级联操作。 </div> | 级联操作更新与删除语法 | 描述 | | ------------------------ | ------------------------------------------------------------------------------------------ | | on update cascade | 级联更新,只能是创建表的时候创建级联关系。更新主表中的主键,从表中的外键列也自动同步更新 | | on delete cascade | 级联删除 | #### 添加级联更新 ```sql alter table employee add constraint emp_dept_id foreign key (dep_id) references department(id) on update cascade; ``` 将`department`销售部`id`改为`9`后,`employee`对应的`dep_id`也改变为`9`。 <div class='album_block'> [album type="photos"] ![](https://blog.fivk.cn/usr/uploads/2021/12/21235214.png) ![](https://blog.fivk.cn/usr/uploads/2021/12/2883645883.png) [/album] </div> 同样,删除了`depattment`的销售部这一条记录,`employee`对应的记录也会别删除。 <div class="tip inlineBlock info"> 这就是级联更新的作用。 </div> #### 删除级联操作 ```sql alter table employee add constraint emp_dept_id foreign key (dep_id) references department(id) on delete cascade; ``` <div class="tip inlineBlock error"> 注意:删除级联操作并不意味着删除外键约束。 </div> # 多表关系 <div class="tip inlineBlock success"> 表关系的概念:现实生活中,实体与实体之间肯定是有关系的。 比如:老公和老婆,部门和员工,老师和学生等。那么我们在设计表的时候,就应该体现出表与表之间的这种关系! </div> ## 多表之间的关系 **表与表之间的三种关系:** | 对应关系 | 实用案例 | | ---------- | ------------------------------------------------------------------------- | | 一对一 | 相对使用比较少。员工表 简历表, 公民表 护照表 | | 一对多 | 最常用的关系 部门和员 | | 多对多 | 学生选课表 和 学生表, 一门课程可以有多个学生选择,一个学生选择多门课程 | **实现关系:** 1. **一对多**:在多的一方建立外键,直线一的一方的主键。 2. **多对多**:在关系实现的时候要借助第三张中间表。中间表至少包含两个字段,这两个字段作为第三张表的外键,分别指向两张表的主键。 3. **一对一**:可以在任意一方添加唯一外键指向另一方主键。 <div class='album_block'> [album type="photos"] ![一对多的关系](https://blog.fivk.cn/usr/uploads/2021/12/2611466358.png) ![多对多的关系](https://blog.fivk.cn/usr/uploads/2021/12/26503640.png) ![一对一关系](https://blog.fivk.cn/usr/uploads/2021/12/2980929248.png) [/album] </div> 最后修改:2022 年 04 月 12 日 © 禁止转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏