# MySQL
**Repository Path**: wcool/sql
## Basic Information
- **Project Name**: MySQL
- **Description**: No description available
- **Primary Language**: SQL
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2021-01-02
- **Last Updated**: 2021-01-06
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# MySQL数据库
------
数据库的结构:
database 数据库 ---> table 表结构 ---> 字段 ---> 数据
- **MySQL相关的配置**
Windows的终端连接数据库:
将 MySQLxx 下的 bin 文件夹路径添加到 环境变量中,比如:
```txt
此为 bin文件目录
C:\phpstudy_pro\Extensions\MySQL5.7.26\bin
win10下:
此电脑 -> 属性 -> 高级系统设置 -> 高级中的环境变量 -> 系统变量中的Path -> 编辑 -> 新建 -> 复制 bin文件目录 -> 确定
```
- **登录MySQL服务器**
```txt
mysql -uroot -p
-u 输入账号,默认账号是root
-p 默认密码,没有密码
```
------
## 1 数据库(DATABASE/DB)操作
建立数据库
```sql
CREATE DATABASE IF NOT EXISTS `samsql` DEFAULT CHARSET UTF8;
-- 简写
CREATE DATABASE `samsql`;
-- CREATE 建立
-- DATABASE 数据库
-- IF NOT EXISTS 不存在的时候再去建立
-- `samsql` 数据库的库名, `` 是反引号,不是引号
-- DEFAULT 默认
-- DEFAULT CHARSET UTF8 默认字符集UTF8
-- CHARSET 可以写成 CHARACTER SET
```
查看数据库
```sql
SHOW DATABASES;
```
查看数据库建立方式,相关信息
```sql
SHOW CREATE DATABASE IF NOT EXISTS `samsql`;
-- 或
SHOW CREATE DATABASE `samsql`;
```
使用数据库
```sql
USE `samsql`;
```
查看正在使用的数据库
```sql
SELECT DATABASE();
```
修改数据库
```sql
ALTER DATABASE `samsql` DEFAULT CHARSET = GBK;
-- 或
ALTER DATABASE `samsql` CHARSET GBK;
```
删除数据库
```sql
DROP DATABASE IF EXISTS `samsql`;
-- 或
DROP DATABASE `samsql`;
```
------
## 2 数据表(TABLE)操作
建立表
```sql
CREATE TABLE IF NOT EXISTS `use1`(
`name` CHAR(30)
)ENGINE INNODB CHARSET UTF8 COMMENT '表结构1';
-- 说明:
-- ENGINE INNODB 设定引擎为InnoDB
-- CHARSET UTF8 编码格式为UTF8
-- COMMENT '表结构1' :设定表结构注释说明
```
查看当前数据库中的所有表结构
```sql
SHOW TABLES;
```
查看表结构的建立方式
```sql
SHOW CREATE TABLE `use1`;
```
查看表中字段的建立方式,设定信息
```sql
DESC `use1`;
```
删除表
```sql
DROP TABLE `use1`;
```
修改表
```sql
-- 可以修改一个属性,也可以同时修改多个属性,只需要将修改的属性逐一设定即可
ALTER TABLE `use1` ENGINE MYISAM;
ALTER TABLE `use1` CHARSET GBK;
ALTER TABLE `use1` COMMENT '第一个建立的表结构';
-- 一次性修改上面的三个
ALTER TABLE `use1` ENGINE INNODB CHARSET UTF8 COMMENT '表结构1';
```
------
## 3 字段操作
### 3.1 查看字段
看表结构中字段的属性
```txt
DESC `表结构名称`;
```
查看建立表结构的属性以及字段属性
```txt
SHOW CREATE TABLE `表结构名称`;
```
### 3.2 修改字段
不管是哪种修改,等于将字段重新建立,所有的属性,约束条件,注释,都要重新设定。
1、修改字段字段以及约束条件
`ALTER...MODIFY`
语法:
```txt
ALTER TABLE `表结构名称` MODIFY `字段名称` 数据类型 属性 约束条件 注释;
```
示例:
```sql
ALTER TABLE `use1` MODIFY `name` VARCHAR(100) NOT NULL COMMENT '存储姓名字段,不能为空';
```
2、修改字段名称,属性以及约束条件
`ALTER...CHANGE`
语法:
```txt
ALTER TABLE `表结构名称`
CHANGE `旧字段名称` `新字段名称` 数据类型 属性 约束条件 注释;
```
示例:
```sql
ALTER TABLE `use1` CHANGE `name` `xingming` VARCHAR(50) NOT NULL COMMENT '存储姓名字段,不能为空';
```
### 3.3 新增字段
`ALTER...ADD...`
默认新增
新增字段会在所有字段之后.
```txt
ALTER TABLE `表名` ADD `新增字段名` 数据类型 属性 约束条件 注释;
```
```sql
ALTER TABLE `use1` ADD `addr` VARCHAR(100) NOT NULL COMMENT '存储员工地址字段';
```
指定字段之前新增
新增字段会在指定字段之前
`ALTER...ADD...FIRST`
FIRST写在所有新增字段设定之后(注释说明后)
```txt
ALTER TABLE `表名` ADD `新增字段名` 数据类型 属性 约束条件 注释 FIRST;
```
```sql
ALTER TABLE `use1` ADD `addr1` VARCHAR(100) NOT NULL COMMENT '存储员工地址字段' FIRST;
```
指定字段之后新增
新增字段会在指定字段之后.
`ALTER...ADD...AFTER 指定字段名称`
AFTER写在所有新增字段设定之后(注释说明后)
```txt
ALTER TABLE `表名` ADD `新增字段名` 数据类型 属性 约束条件 注释 AFTER `指定字段`;
```
```sql
-- 例如:在性别(sex)之后新增字段
ALTER TABLE `use1` ADD `addr2` VARCHAR(100) NOT NULL COMMENT '存储员工地址字段' AFTER `sex`;
```
### 3.4 删除字段
`ALTER...DROP`
删除一条
```txt
ALTER TABLE `表结构名称` DROP `字段名称`;
```
```sql
-- 删除addr2字段
ALTER TABLE `use1` DROP `addr2`;
```
删除多条
```txt
ALTER TABLE `表结构名称` DROP `字段1` , DROP `字段2`...;
```
```sql
-- 删除多个字段
-- 多个字段,都要添加DROP关键词,每个删除字段之间使用逗号间隔,最后使用分号结束
ALTER TABLE `use1` DROP `addr`,DROP `addr1`;
```
------
## 4 字段的数据类型
### 4.1 整数类型
设定数据类型,不同类型有不同的数值范围,输入的数据不能超过书类型的范围。
通过字段属性定义有符号,无符号位,默认为有符号位属性。
整数类型(M):
M可以设定输入数值的位数。
但是输入的数据,只要不超过最大值或者默认位数,都可以正常输入;
实际项目中,M值没有约束效果,一般不做设定,执行默认位数。
#### TINYINT
1个字节,默认最多存储4位数字。
```txt
有符号位,数值有正负,
范围是:-128至127 -2^7至2^7-1
无符号位,数值从0开始,
范围是:0至255 0至2^8-1
```
#### SMALLINT
2个字节,默认最多存储6位数字。
```txt
有符号位,数值有正负,
范围是:-32768至32767
无符号位,数值从0开始,
范围是:0至65535
```
#### MEDIUMINT
3个字节,默认最多存储9位数字。
```txt
有符号位,数值有正负,
范围是:-8388608 至 8388607
无符号位,数值从0开始,
范围是:0 至 16777215
```
#### INT
4个字节,默认最多存储11位数字。
```txt
有符号位,数值有正负,
范围是:-2147483648 至 2147483647
无符号位,数值从0开始,
范围是:0 至 4294967295
```
#### BIGINT
8个字节,默认最多存储位20数字。
```txt
有符号位,数值有正负,
范围是:-9223372036854775808 至 9223372036854775807
无符号位,数值从0开始,
范围是:0 至 18446744073709551615
```
### 4.2 浮点类型
`浮点类型(M,D)`
M 设定整个数值的数字位数
D 设定小数部分数值位数
#### 常用单精度浮点数 FLOAT
```txt
范围:-3.40e38 至 3.40e38
最多7位小数
```
```sql
FLOAT(7,4)
-- 小数部分最多4位
-- 整个数值是7位,小数4位,整数部分最多3位
```
#### 双精度浮点数 DOUBLE
```txt
范围:-1.79e308 至 1.79e308
最多15位小数
```
#### 定长浮点数 DECIMAL
```txt
范围:
最多存储65位数值,小数部分最多30位;
默认整数部分为10位,小数部分为0位。
```
### 4.3 文本类型
文本类型(M)
设定存储字符的位数
#### 定长字符 CHAR
最多255个字符;
如果输入的数据长度小于设定字符位数,会在数据尾部补充空格。
使用范围:身份证号,手机号,md5(),sha1() ...
#### 变长字符 VARCHAR
最多存储65535个字符;
设定存储字符长度数值,与编码格式,与其他字段数据类型相关。
使用范围:姓名,地址 ...
#### TINYTEXT
最多255个字符。
#### TEXT
最多65535个字符。
#### MEDIUMTEXT
最多16777215个字符。
#### LONGTEXT
最多4GB内容。
### 4.4 日期类型
YEAR(M)
YEAR(2) 表示两位年份,范围:1-99
YEAR(4) 表示四位年份,范围:1901-2155
#### DATE
```txt
YYYY-MM-DD
4位年,2位月,2位日期
支持范围:
1000-01-01 至 9999-12-31
```
#### TIME
```txt
HH:MM:SS
2位小时,2位分钟,2位秒
支持范围:
-838:59:59 至 838:59:59
```
#### DATETIME
```txt
YYYY-MM-DD HH:MM:SS
支持范围:
1000-01-01 00:00:00 至 9999-12-31 23:59:59
```
#### TIMESTAMP
```txt
自动获取当前时间戳,存储时间
支持范围:
1970-01-01 0:0:0 至 2038-1-9 03:14:07
```
### 4.5 枚举类型 ENUM
可以设定输入的数据内容,执行数据写入操作时,必须是设定范围内的数据。
**一次只能写入一个数据,单选效果。**
最多设定65535个数值。
ex:
```sql
ENUM('男','女','保密')
```
### 4.6 集合类型 SET
可以设定输入的数据内容,执行数据写入操作时,必须是设定范围内的数据。
**一次可以输入多个数组,多选效果。**
最多设定64个列表项目。
ex:
```sql
SET('吃','喝','玩','乐')
```
### 4.7 布尔类型 BOOLEAN
BOOLEAN 与 TINYINT(1)
最终执行效果为TINYINT(1),实际数据的输入范围为 -128 至 127 之间。
0为false 非0为true
------
## 5 字段的属性以及约束条件
### 5.1 字段属性
字段属性主要是针对整数类型定义。
#### UNSIGNED
非负属性,设定无符号位属性。
#### ZREOFILL
自动补零,如果输入的数据,不够设定的字符位数,会在数值前自动补零.
添加ZEROFILL属性的字段,会自动添加UNSIGNED属性.
### 5.2 字段约束条件
#### NOT NULL
非空属性,数据输入不能为空。
#### DEFAULT
默认值属性,如果没有输入数据,或者输入数据为DEFAULT,执行设定的默认值。
#### UNIQUE KEY
唯一索引,字段输入的数据不能重复,自动创建系统的唯一索引表结构。
#### PRIMARY KEY
主键索引,一个表结构只能一个字段有主键约束。
给字段添加主键约束,类似于id属性,与数据是一一对应效果。
功能:
1、主键约束的字段,输入的数据不能为空;
2、主键约束的字段,输入的数据不能重复;
3、会自动创建系统主键索引表结构。
一般与 AUTO_INCREMENT (自增属性) 配合使用,自动给id约束字段写入数据。
#### FOREIGN KEY
外键约束
## 附1 建立表结构实例
```sql
-- 建立表结构
-- 字段名称 数据类型 属性 约束条件 注释说明
-- 定义多个字段,以逗号间隔,最后一个字段不要添加逗号
-- 带有主键值约束字段一般名称为id,带有非负属性,自增属性
CREATE TABLE`use1`(
`id` SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT '主键字段',
`name` VARCHAR(30) NOT NULL COMMENT '姓名字段',
`age` TINYINT ZEROFILL NOT NULL DEFAULT 18 COMMENT '年龄字段,默认18',
`sex` ENUM('男','女','保密') NOT NULL DEFAULT '保密' COMMENT '性别字段,数值范围:男、女、保密,单选,默认值为保密',
`hobby` SET('吃','喝','玩','乐') NOT NULL DEFAULT '吃' COMMENT '爱好字段,数值范围:吃、喝、玩、乐,多选,默认值为吃',
`phone` CHAR(11) NOT NULL UNIQUE KEY COMMENT '手机号字段,不能为空,不能重复',
`pay` FLOAT(10,3) NOT NULL DEFAULT '5000' COMMENT '薪资字段,最多7位整数3位小数,默认值为5000.000',
`online` BOOLEAN DEFAULT 1 COMMENT '在线字段,布尔类型,默认值为1,在线状态',
`time` TIMESTAMP COMMENT '时间字段,默认自动获取当前时间'
)ENGINE INNODB CHARSET UTF8 COMMENT '创建表结构1,演示数据类型以及数据写入';
-- SMALLINT 数据类型 2个字节,默认最多存储6位数字。
-- UNSIGNED 属性 非负属性,设定无符号位属性。
-- PRIMARY KEY 约束条件 主键索引,配合 AUTO_INCREMENT 使用
-- AUTO_INCREMENT 自增属性
-- VARCHAR 数据类型 变长字符;最多存储65535个字符;
-- NOT NULL 属性 非空属性,数据输入不能为空。
-- TINYINT 数据类型 1个字节,默认最多存储4位数字。
-- ZEROFILL 属性 自动补零
-- DEFAULT 属性 默认属性
-- ENUM 数据类型 单选
-- SET 数据类型 多选
-- CHAR 数据类型 定长字符;最多255个字符;如果输入的数据长度小于设定字符位数,会在数据尾部补充空格。
-- UNIQUE KEY 约束条件 唯一索引,字段输入的数据不能重复
-- FLOAT 数据类型 单精度浮点数,最多15位小数
-- BOOLEAN 数据类型 0为false 非0为true
-- TIMESTAMP 数据类型 自动获取当前时间戳,存储时间
```
## 6 数据的写入 INSERT
1、对表结构中,指定的字段,写入数据
```txt
INSERT `表结构名称` (`字段名称1` , `字段名称2` , `字段名称3`...)
VALUES (数据1,数据2,数据3...);
```
示例:
```sql
INSERT `use1`(`name`,`age`,`sex`,`hobby`,`phone`,`pay`,`online`)
VALUES ('赵六',22,'女','吃,喝','12345691',20000,1);
```
2、对表结构中所有的字段写入数据
```txt
INSERT `表结构` VALUES ();
```
如果有不想输入数据的字段,可以使用NULL或者DEFAULT(推荐)。
如果字段有NOT NULL约束,不能输入NULL数据。
示例:
```sql
INSERT `use1` VALUES(null,'刘七',50,'保密','喝','123',200,1,null);
INSERT `use1` VALUES(DEFAULT,'王二麻子',50,'保密','喝','1234',200,1,DEFAULT);
INSERT `use1` VALUES(DEFAULT,'李雷',60,'保密','喝','12346',null,1,DEFAULT);
INSERT `use1` VALUES(DEFAULT,'李雷',60,'保密','喝','12346',DEFAULT,1,DEFAULT);
```
说明:
1、字段名称,数据之间使用逗号间隔;
2、设定的字段,必须与写入的数据一一对应;
3、id主键值,TIMESTAMP,相关字段,一般不写入数据;
4、输入的数据,如果是数值,不用添加引号,如果是非数字,必须添加引号(单引号或者双引号) 名称反引号,数据单引号;
5、枚举类型和集合类型,必须输入设定的数值;
6、集合类型,如果需要输入多个数据,将多个数据定义在一个字符串中,使用逗号间隔;
7、枚举类型只能单选,一次只能输入一个数据;
8、带有唯一主键约束的字段,不能输入重复数据;
9、如果输入错误数据,有可能会引起id主键值的自增;
10、对于不存在的id主键值,可以定义id主键值,写入数据,对于已经存在的id主键值,不能重复写入数据;
11、对于不想输入数组的字段,推荐使用DEFAULT,如果没有NOT NULL属性的字段也可以使用NULL;
12、DEFAULT会执行默认值或者自增数值,或者自动获取数值;
13、DEFAULT和NULL 不用写引号。
## 7 数据的修改 UPDATE...SET
1、修改表结构中,指定字段的所有数据
将表结构中,该字段的所有数据,修改为设定数据.
```txt
UPDATE `表名` SET `字段名` = 数据;
```
示例:
```sql
-- 将字段name的所有数据,都设定为李四
UPDATE `use1` SET `name` = '李四';
```
2、修改表结构中,符合约束条件的字段的数据
将表结构中,该字段符合约束条件的数据,修改为指定数据.
```txt
UPDATE `表名` SET `字段名` = 数据 WHERE 约束条件;
```
示例:
```sql
-- 将id主键值是3的数据,name字段中的数据,修改为张三
-- id主键值唯一不重复,匹配的数据只有一条
UPDATE `use1` SET `name` = '张三' WHERE `id` = 3;
-- 匹配数据可以是一条,也可以是多条
-- 将所有sex字段数据为保密的,修改为女
UPDATE `use1` SET `sex` = '女' WHERE `sex` = '保密';
```
## 8 数据的删除 DELETE / TRUNCATE
DELETE逐行删除,TRUNCATE删除整个表结构;
DELETE不会重置自增字段属性,TRUNCATE会重置自增字段属性;
DELETE会触发触发器,TRUNCATE不会触发触发器;
DELETE会进行事物回滚,TRUNCATE不会进行事物回滚。
#### DELETE
1、删除表结构中的所有数据,保留id主键值
```txt
DELETE FROM `表名`;
```
示例:
```sql
-- 删除数据库,表结构中的所有数据
-- 保留id主键值
-- 新增数据,会顺延之前id主键值的最大值
DELETE FROM `use1`;
```
2、删除表结构中,符合约束条件的数据
```txt
DELETE FROM `表名` WHERE 约束条件;
```
示例:
```sql
-- 删除数据库中,匹配约束条件的相关数据
-- 匹配数据是一条
DELETE FROM `use1` WHERE `id` = 1;
-- 匹配数据是多条
DELETE FROM `use1` WHERE `age` = 21;
```
#### TRUNCATE
直接删除表结构中的所有数据,并且不保留id主键值.
只能删除表结构中的所有数据,不能设定WHERE关键词.
```txt
TRUNCATE TABLE `表名`;
```
示例:
```sql
TRUNCATE TABLE `use1`;
```
## 9 数据的查询 SELECT
`as` 别名 ,别名不加引号,可以加反引号
示例:
```sql
SELECT DATABASE() as DB;
-- 或
SELECT DATABASE() as `DB`;
-- 这里的 DB 就是别名
```
**字符串转化函数:**
```txt
LOWER() 字符小写
UPPER() 字符大写
SUBSTR() 字符截取
CONCAT() 字符拼接
```
**算数运算符:**
```txt
+
-
*
/
%
CEIL() 向上取整
FLOOR() 向下取整
POW() 乘方运算
```
**比较运算符:**
```txt
> < = >= <=
```
`=` 既是判断是否相等的比较运算符,也是赋值运算符。
`!=` 不等于判断,推荐使用这个不等于 `<>`
判断null 用 `is null` 和 `is not null`
**逻辑运算符:**
```txt
逻辑与 and
逻辑或 or
逻辑非 not
```
**语法格式:**
```txt
SELECT * `字段名` `聚合函数` as `别名`
FROM `表名` 子查询 as `别名`
WHERE 字段的约束条件
GROUP BY `字段名` 分组查询
HAVING 聚合函数的约束条件
ORDER BY 设定显示查询顺序
LIMIT 参数1,参数2 分页显示
```
**数据查询操作说明:**
1, 所有复杂的查询,都是一个一个约束条件的堆砌
2, 名称用反引号,数据字符串 用单引号
3, 字段约束用WHERE, 聚合函数约束用HAVING
4, LIMIT数据的下标,不是id主键值
5, 语法顺序:
- SELECT
- FROM
- WHERE 字段约束
- GROUP BY 分组查询
- HAVING 聚合函数约束
- ORDER BY 顺序
- LIMIT 分页
### 9.1 基本查询方式
查询表结构中指定字段的所有数据。
凡是需要设定显示的内容或者是查询的内容,都放在 `SELECT` 和 `FROM` 之间。
语法:
```txt
SELECT *或者`字段名称` FROM `表名`;
```
`*` 通配符,表示任意字段.
示例:
```sql
-- 查询 use2 表结构中的所有数据
SELECT * FROM `use2`;
-- 可以在SELECT与FROM之间定义字段名称,来查询指定字段的数据
-- 字段之间以逗号间隔
-- 可以给字段添加别名,显示的表头就是定义的别名
-- 可以设定字段顺序,查询结果以设定字段顺序显示
SELECT `id` as `序号` , `name` as `姓名` , `age` as `年龄` FROM `use2`;
```
### 9.2 字段的约束条件 WHERE
`WHERE` 的约束条件是针对字段的约束条件.
`WHERE` 针对字段数据的约束条件,支持比较运算符,逻辑运算符等。
凡是对于字段数据的约束都写在 `WHERE` 之内。
```sql
-- 查询年龄大于20的员工信息,需要显示id,姓名,年龄,部门
-- 年龄大于20
-- 年龄是表结构中已有的字段
-- `age`>20 对已有字段的数据的约束条件
-- 使用WHERE关键词
SELECT `id`,`name`,`age`,`dep` FROM `use2` WHERE `age` > 20;
-- 查询年龄大于20并且小于25,性别为男性,薪资超过15000的员工的所有信息
-- 年龄 `age`>20 AND `age`<25
-- 性别 `sex` = '男'
-- 薪资 `pay`>15000
SELECT * FROM `use2` WHERE (`age` > 20 AND `age` < 25) AND `sex` = '男' AND `pay` > 15000;
-- 使用()提高优先级,让程序员的执行逻辑更加准确
-- 查询 北京小于25岁的员工,显示id,姓名,年龄,城市,部门
-- 北京 `city`='北京'
-- 年龄 `age`<25
-- 显示 `id` , `name` , `age` , `city` , `dep`
SELECT `id`,`name`,`age`,`city`,`dep` FROM `use2` WHERE `city`='北京' AND `age`<25;
```
### 9.3 分组查询 GROUP BY
将指定字段中的数据按照数值分组显示,相同的数值分为一组,一组之内默认只显示查询到的第一条数据,但实际分组中有所有相同数值的数据。
语法:
```txt
GROUP BY `字段名称`
```
示例:
```sql
SELECT * FROM `use2` GROUP BY `city`;
```
注意:如果执行以上 `GROUP BY` 语句出现类似以下报错
> ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'samsql.use2.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
用记事本打开my.cnf文件(文件名有可能叫 My.ini),然后在 `[mysqld]` 后面追加下面这句配置,最后重启 `mysql` 服务。
```txt
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
```
### 9.4 聚合函数
对分组中的所有数组,执行聚合函数的效果。
聚合函数往往定义在 `SELECT` 与 `FROM` 之间,作为查询或显示的数据。
| 语法 | 作用 |
|--- |--- |
| COUNT() | 数据数量 |
| MIN() | 最小值 |
| MAX() | 最大值 |
| AVG() | 平均值 |
| SUM() | 求和 |
### 9.5 聚合函数 与 GROUP BY 配合使用
聚合函数 是对 `GROUP BY` 分组中的所有数据,执行聚合函数效果。
示例1:
```sql
-- 查询每个部门的人数,显示部门,显示人数
-- 每个部门:按照部门进行分组查询
-- 人数:数据数量 COUNT()
SELECT `dep` as `部门`, COUNT(`dep`) as `人数` FROM `use2` GROUP BY `dep`;
```
示例2:
```sql
-- 每个城市的员工人数 COUNT(`city`) 显示城市、人数
-- 每个城市 GROUP BY `city`
-- 人数 COUNT(`city`)
SELECT `city` as `城市`, COUNT(`city`) as `人数` FROM `use2` GROUP BY `city`;
```
示例3
```sql
-- 每个城市员工的平均年龄 AVG(`age`) 显示城市、平均年龄
-- 每个城市 GROUP BY `city`
-- 平均年龄 AVG(`age`)
SELECT `city`, AVG(`age`) FROM `use2` GROUP BY `city`;
```
示例4
```sql
-- 每个城市员工的平均薪资 MAX(`pay`) 显示城市、最大薪资
-- 每个城市 GROUP BY `city`
-- 最大薪资 MAX(`pay`)
SELECT `city`, MAX(`pay`) FROM `use2` GROUP BY `city`;
```
### 9.6 聚合函数的约束条件 HAVING
`HAVING` 与 `WHERE` 的区别:
`WHERE` 是字段的约束条件,约束对象是表结构本身就具有的字段。
`HAVING` 是聚合函数的约束条件,约束对象是聚合函数执行的结果,不是表结构本身就具有的数据。
语法:
```txt
GROUP BY `字段名称` HAVING 聚合函数约束条件
```
示例:
```sql
-- 显示部门人数超过30人的部门
-- 部门人数
-- 按照部门分组,求聚合函数COUNT()的数值
-- 人数超过30人:人数是COUNT()的执行结果,约束条件是针对聚合函数的,需要使用HAVING来限定
SELECT `dep` as `部门`,COUNT(*) as `人数` FROM `use2` GROUP BY `dep` HAVING COUNT(*)>30;
-- 显示平均年龄超过23岁的部门
-- 按照部门进行分组查询
-- 平均年龄,聚合函数 AVG(`age`)
-- 平均年龄>23 聚合函数 AVG(`age`)>23,使用HAVING
SELECT `age`,AVG(`age`) FROM `use2` GROUP BY `age` HAVING AVG(`age`)>30;
-- 显示最大薪资超过20000的城市
-- 最大薪资 MAX(`pay`)
-- 最大薪资>20000 聚合函数 MAX(`pay`)>20000,使用HAVING
-- 按照城市分组 GROUP BY `city`
SELECT `city`,MAX(`pay`) FROM `use2` GROUP BY `dep` HAVING MAX(`pay`)>20000;
-- 显示平均年龄小于23岁的城市
-- 平均年龄 AVG(`age`)
-- 平均年龄<23 AVG(`age`)<23
-- GROUP BY `city`
SELECT `city`,AVG(`age`) FROM `use2` GROUP BY `city` HAVING AVG(`age`)<23;
-- 显示人数大于30人的部门
-- 按照部门进行分组 GROUP by `dep`
-- 人数 COUNT(`dep`)
-- 部门人数>30 COUNT(`dep`)>30 聚合函数,使用HAVING
SELECT `dep`,COUNT(`dep`) FROM `use2` GROUP BY `dep` HAVING COUNT(`dep`)>30;
```
### 9.7 WHERE 与 GROUP BY 与 HAVING的配合使用
`WHERE` 约束条件与 `GROUP BY` 分组查询与聚合函数 `HAVING` 配合使用。
示例:
```sql
-- 查询每个部门的人员数量
SELECT `dep`,COUNT(`dep`) FROM `use2` GROUP BY `dep`;
-- 查询每个部门年龄超过25岁的人员数量
-- 每个部门 GROUP BY `dep`
-- 人员数量 COUNT(`dep`)
-- 年龄大于25岁 `age`>25 这是字段用 WHERE
-- 将数据中年龄age字段中大于25的数据按照部门dep字段分组
-- 再求分组中的数据数量
SELECT `dep`,COUNT(`dep`) FROM `use2` WHERE `age`>25 GROUP BY `dep`;
-- 查询每个部门年龄超过25岁的人员数量,只显示人员数量超过10人的部门
-- 每个部门 GROUP BY `dep`
-- 人员数量 COUNT(`dep`)
-- 年龄大于25岁 `age`>25 这是字段用 WHERE
-- 人员数量超过10人 COUNT(`dep`)>10 这是聚合函数用 HAVING
SELECT `dep`,COUNT(`dep`) FROM `use2` WHERE `age`>25 GROUP BY `dep` HAVING COUNT(`dep`)>10;
```
### 9.8 显示顺序 ORDER BY
设定显示查询结果的显示顺序。默认按照id的升序显示。
可以设定多个字段的显示顺序,多个之间用逗号隔开,有显示优先级。
语法:
```txt
ORDER BY `字段` 显示顺序
参数:
ASC 默认显示顺序,升序,小-大
DESC 降序 大-小
```
示例:
```sql
-- 默认查询结果按照id升序显示
SELECT * FROM `use2`;
-- 按照薪资的降序排列 DESC
SELECT * FROM `use2` ORDER BY `pay` DESC;
-- 按照年龄的升序排列 ASC,默认方式,推荐不写
SELECT * FROM `use2`ORDER BY `age`;
-- 可以设定多个字段的显示顺序,有显示优先级
-- 按照年龄的升序id的降序排列
SELECT * FROM `use2` ORDER BY `age` , `id` DESC
```
### 9.9 分页显示 LIMIT
只显示查询结果的部分数据。
有两个参数需要设定:
参数1为 起始数据的小标,从0开始的数值,
参数2为 显示的数据数量。
语法:
```txt
LIMIT 参数1,参数2
```
示例:
```sql
-- 查询PHP部门年龄最大的10个人
-- PHP部门: `dep` = 'PHP' 字段的约束条件用WHERE
-- 年龄最大的10个人: 前10个数据,从0开始,显示10条
-- 年龄最大的10个人: 年龄从大至小显示 ORDER BY `age` DESC
SELECT `dep`,`age` FROM `use2` WHERE `dep`='PHP' ORDER BY `age` DESC LIMIT 0,10;
-- 查询北京市挣钱最少的3个人
-- 北京市: `city` = '北京' 用WHERE
-- 3个人: LIMIT 0,3
-- 挣钱最少的3个人: ORDER BY `pay` 升序不写
SELECT `city`,`name`,`pay` FROM `use2` WHERE `city`='北京' ORDER BY `pay` LIMIT 0,3;
```
## 10 子查询
将查询结果作为约束条件。
子查询中的查询语句必须添加小括号,提高优先级优先执行。
将查询结果作为其他查询的条件。
示例:
```sql
-- 查询年龄超过大脸猫年龄的员工信息
--
-- 年龄大于大脸猫年龄 `age`>20 这是一个字段的约束条件,用WHERE
-- 先查询`name`字段,数据是大脸猫的员工的`age`数据
SELECT `age` FROM `use2` WHERE `name`='大脸猫';
-- 结果为20
-- 该结果应该是另一个查询语句的条件
-- 子查询
SELECT `age`,`name` FROM `use2` WHERE `age` > (SELECT `age` FROM `use2` WHERE `name`='大脸猫');
-- 查询挣钱比大脸猫多的人
--
-- `pay` > 大脸猫的`pay`
-- 查询大脸猫的薪资
SELECT `pay` FROM `use2` WHERE `name`='大脸猫';
-- 子查询
SELECT `pay`,`name` FROM `use2` WHERE `pay` > (SELECT `pay` FROM `use2` WHERE `name`='大脸猫')
-- 查询大脸猫的同事
SELECT `name`,`dep` FROM `use2` WHERE `dep`=(SELECT `dep` FROM `use2` WHERE `name`='大脸猫');
-- 查询大脸猫的同城
SELECT `name`,`city` FROM `use2` WHERE `city`=(SELECT `city` FROM `use2` WHERE `name`='大脸猫');
-- 查询比大脸猫挣钱多的男同事
SELECT `name`,`sex`,`pay` FROM `use2` WHERE `sex`='男' AND `pay`>(SELECT `pay` FROM `use2` WHERE `name`='大脸猫');
-- 查询薪资数据大于大脸猫薪资数据,部门数据等于大脸猫数据,性别为男
SELECT `name`,`sex`,`pay`,`dep` FROM `use2` WHERE `sex`='男' AND `pay`>(SELECT `pay` FROM `use2` WHERE `name`='大脸猫') AND `dep`=(SELECT `dep` FROM `use2` WHERE `name`='大脸猫');
-- 查询比大脸猫年轻
SELECT `name`,`age` FROM `use2` WHERE `age`<(SELECT `age` FROM `use2` WHERE `name`='大脸猫');
```
### IN(子查询)
子查询结果是等于所有结果中的任意一个。
语法:
```sql
SELECT * FROM `use1` WHERE id IN(3,4,5,6);
-- IN 等于()中的任意一个数值即可,逻辑OR的关系
-- IN 之前和之后都不要添加比较运算符
```
子查询的查询结果如果是多个数据结果,不能直接使用比较运算符。需要添加关键词
示例:
```sql
-- 查询大脸猫,早安霖,张志远三个人的工资
SELECT `pay` FROM `use2` WHERE `name` IN('大脸猫','早安霖','张志远');
-- 查询薪资与大脸猫,早安霖,张志远薪资相同的人员信息
-- SELECT `name`,`pay` FROM `use2` WHERE `pay`=(SELECT `pay` FROM `use2` WHERE `name`='大脸猫') OR `pay`=(SELECT `pay` FROM `use2` WHERE `name`='早安霖') OR `pay`=(SELECT `pay` FROM `use2` WHERE `name`='张志远');
SELECT `name`,`pay` FROM `use2` WHERE `pay` IN(SELECT `pay` FROM `use2` WHERE `name` IN('大脸猫','早安霖','张志远'));
```
### ANY(子查询)
子查询结果为 大于或者小于所有结果中的任意一个。大于最小值,小于最大值。
大于或者小于**任意**数值 > < >= <= 逻辑OR的关系。
大于最小值,就是大于任意,小于最大值,就是小于任意。
语法:
```txt
SELECT * FROM `use1` WHERE pay > ANY(子查询);
```
示例:
```sql
-- 年龄大于大脸猫,早安霖,张志远中任意年龄
-- 1. 大脸猫,早安霖,张志远的年龄
SELECT `age` FROM `use2` WHERE `name` IN('大脸猫','早安霖','张志远');
-- 2. 大于大脸猫,早安霖,张志远中任意年龄
SELECT `name`,`age` FROM `use2` WHERE `age` > ANY(SELECT `age` FROM `use2` WHERE `name` IN('大脸猫','早安霖','张志远'));
-- 薪资小于大脸猫,早安霖,张志远中任意薪资
SELECT `name`,`pay` FROM `use2` WHERE `pay` < >= <= 逻辑AND关系。
大于最大值,才是大于所有,小于最小值,才是小于所有。
语法:
```txt
SELECT * FROM `use1` WHERE pay > ALL(子查询);
```
示例:
```sql
-- 查询薪资比 大脸猫,早安霖,张志远三个人的薪资都高的人员
--
-- 1. 查询大脸猫,早安霖,张志远的薪资
SELECT `pay` FROM `use2` WHERE `name` IN('大脸猫','早安霖','张志远');
-- 2. 查询薪资比 大脸猫,早安霖,张志远三个人的薪资都高的人员
SELECT `name`,`pay` FROM `use2` WHERE `pay` > ALL(SELECT `pay` FROM `use2` WHERE `name` IN('大脸猫','早安霖','张志远')) ORDER BY `pay` DESC;
-- 薪资大于所有部门平均薪资人员信息
--
-- 1. 所有部门平均薪资
SELECT AVG(`pay`) FROM `use2` GROUP BY `dep`;
-- 2. 薪资大于所有部门平均薪资人员
SELECT `dep`,`pay` FROM `use2` WHERE `pay` > ALL(SELECT AVG(`pay`) FROM `use2` GROUP BY `dep`);
```
## 11 联合查询
多个表结构的查询。
节省存储空间,提高数据的使用效率,父表存储文字,子表存储父表文字得id主键值,查询时,通过联合查询将子表中的数值显示为父表中的文字。
### 内连接 INNER JOIN...ON
两个表结构相关联的部分. `INNER JOIN` 对于不匹配的内容,不会显示.
如果有多个父表需要导入,要写入多个 `INNER JOIN ... ON`
语法:
```txt
INNER JOIN `父表名`
ON 子表.字段=父表.id主键值
```
示例图1:

示例图2:

示例图3:

示例子表父表数据:
```sql
-- 性别父表
CREATE TABLE `sexTab`(
`id` TINYINT UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT 'id主键值字段',
`sexFar` ENUM('男','女','保密') COMMENT '性别字段,枚举类型,可以输入值为男,女,保密'
)ENGINE InnoDB CHARSET UTF8 COMMENT '性别父表,存储性别文字';
-- 写入数据
INSERT `sexTab` (`sexFar`) VALUES ('男'),('女'),('保密');
-- 城市父表
CREATE TABLE `cityTab`(
`id` TINYINT UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT 'id主键值字段',
`cityFar` VARCHAR(30) COMMENT '城市字段'
)ENGINE InnoDB CHARSET UTF8 COMMENT '城市父表,存储城市文字';
-- 写入数据
INSERT `cityTab` (`cityFar`) VALUES ('北京'),('上海'),('广州'),('重庆'),('天津');
-- 部门父表
CREATE TABLE `depTab`(
`id` TINYINT UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT 'id主键值',
`depFar` VARCHAR(30) COMMENT '部门字段'
)ENGINE InnoDB CHARSET UTF8 COMMENT '部门父表,存储部门文字';
-- 写入数据
INSERT `depTab` (`depFar`) VALUES ('PHP'),('JAVA'),('WEB'),('UI/UE');
-- 建立子表use3 之前存储文字的部分,存储数值(文字对应的id主键值)
-- 子表中存储父表id主键值的字段,数据类型必须 与父表id主键值的数据类型完全一致
CREATE TABLE `use3`(
id SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
name VARCHAR(30) NOT NULL COMMENT '员工姓名',
age TINYINT UNSIGNED DEFAULT 18 COMMENT '员工年龄,默认18岁',
sex TINYINT UNSIGNED DEFAULT 3 COMMENT '员工性别,子表字段,存储父表id主键值,1=男,2=女,3=保密,默认值为3保密',
city TINYINT UNSIGNED NOT NULL COMMENT '员工所在城市,子表字段,存储父表id主键值,1=北京,2=上海,3=广州,4=重庆,5=天津,',
dep TINYINT UNSIGNED NOT NULL COMMENT '员工所在部门,子表字段,存储父表id主键值,1=PHP,2=JAVA,3=WEB,4=UI/UE',
pay FLOAT(8,2) DEFAULT 5000 COMMENT '员工薪资'
)ENGINE = InnoDB CHARSET = UTF8 COMMENT = '员工信息表,子表结构,存储的是父表的id主键值';
-- 存储数据时,要将文字转化为对应数值
INSERT `use3`(name,age,sex,city,dep,pay)
VALUES
('王卓',21,3,2,1,15000),
('Andy',27,1,3,3,9000),
('半世浮夸',22,1,4,1,6000),
('梁晓洁',17,2,1,4,8000),
('Eric',23,3,1,2,9000),
('echo不开心',21,1,1,1,15000),
('心竹',22,2,5,1,18000),
('执念',20,1,1,1,19000);
```
执行联合查询,显示为父表中对应的文字
```sql
SELECT u.`id`,`name`,`age`,`sexFar`,`cityFar`,`depFar`,`pay` FROM `use3` as u
INNER JOIN `sexTab` as s
ON u.`sex` = s.`id`
INNER JOIN `cityTab` as c
ON u.`city` = c.`id`
INNER JOIN `depTab` as d
ON u.`dep` = d.`id`
```
**联合查询和其他SQL的使用方法:**
联合查询是一个完整的整体内容,所有的其他SQL语句,都要写在联合查询之后。
语法形式:
```txt
SELECT ... FROM `子表`
INNER JOIN `父表`
ON `子表`.`字段` = `父表`.`id`
其他SQL语句WHERE GROUP BY HAVING ORDER BY LIMIT
```
注意:
其他SQL语句中,如果使用冲突的字段,也要表明字段来源。
要分清数据是子表数据,还是父表数据。
`.` 点的前后最好不要写空格,有些版本中,会显示报错。
示例:
```sql
SELECT `u`.`id`,`name`,`age`,`sexFar`,`cityFar`,`depFar`,`pay` FROM `use3` as `u`
INNER JOIN `sexTab` as `s`
ON `u`.`sex` = `s`.`id`
INNER JOIN `cityTab` as `c`
ON `u`.`city` = `c`.`id`
INNER JOIN `depTab` as `d`
ON `u`.`dep` = `d`.`id`
WHERE `depFar`='PHP'
ORDER BY `u`.`id`;
```
### 左外连接 LEFT JOIN ... ON
会完全显示某个表结构,如果没有对应的数据,显示为NULL。
语法:
```txt
LEFT JOIN `父表名`
ON 子表.字段=父表.id主键值
```
说明图:

示例:
```sql
-- 录入子表新数据,张三性别4,李四城市10,王五部门100
INSERT `use3`(name,age,sex,city,dep,pay)
VALUE
('张三',27,4,1,1,15000),
('李四',23,2,10,1,15000),
('王五',25,1,1,100,15000);
-- 内联接的联合查询,不显示
SELECT `u`.`id`,`name`,`age`,`sexFar`,`cityFar`,`depFar`,`pay` FROM `use3` as `u`
INNER JOIN `sexTab` as `s`
ON `u`.`sex` = `s`.`id`
INNER JOIN `cityTab` as `c`
ON `u`.`city` = `c`.`id`
INNER JOIN `depTab` as `d`
ON `u`.`dep` = `d`.`id`;
-- 内联接的联合查询,张三性别4、李四城市10、王五部门100,没有对应的id主键值,不会显示该数据
-- LEFT 完全显示左表,也就是子表
-- 会完全显示某个表结构,如果没有对应的数据,显示为NULL
SELECT `u`.`id`,`name`,`age`,`sexFar`,`cityFar`,`depFar`,`pay` FROM `use3` as `u`
LEFT JOIN `sexTab` as `s`
ON `u`.`sex` = `s`.`id`
LEFT JOIN `cityTab` as `c`
ON `u`.`city` = `c`.`id`
LEFT JOIN `depTab` as `d`
ON `u`.`dep` = `d`.`id`;
```
### 右外连接 RIGHT JOIN ... ON
右外连接:完全显示右表(父表)中的所有数据,没有关联子表的数据显示为NULL。
语法:
```txt
RIGHT JOIN `父表名`
ON 子表.字段=父表.id主键值
```
说明:

示例:
```sql
SELECT `u`.`id`,`name`,`age`,`sexFar`,`cityFar`,`depFar`,`pay` FROM `use3` as `u`
RIGHT JOIN `sexTab` as `s`
ON `u`.`sex` = `s`.`id`
RIGHT JOIN `cityTab` as `c`
ON `u`.`city` = `c`.`id`
RIGHT JOIN `depTab` as `d`
ON `u`.`dep` = `d`.`id`
ORDER BY `u`.`id`;
```
### 外键 FOREIGN KEY ... REFERENCES ...
外键作用:
将当前表结构中的字段与其他表结构中的字段相关联.
语法:
```txt
FOREIGN KEY (子表字段名) REFERENCES 父表表名(父表字段)
```
说明:
两个关联字段的数据类型以及属性,必须完全相同.
外键要独立建立,并且写在所有的字段设定之后.
外键也是建立表结构的一部分,需要使用逗号间隔,最后一个外键不要添加逗号.
并且关联之后的两个表结构,不能随意删除和修改数据,如果需要删除,要先删除子表,再删除父表.
示例:
```sql
-- 建立use4表结构,其中给sex,city,dep添加外键
-- 普通建立表结构,子表字段的数据类型没有约束,可以是任意数据类型,不一定非要与父表id主键值数据类型相同
CREATE TABLE `use4`(
`id` SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT '主键值字段',
`name` VARCHAR(30) NOT NULL COMMENT '员工姓名',
`age` TINYINT UNSIGNED DEFAULT 18 COMMENT '员工年龄,默认18',
`sex` TINYINT UNSIGNED DEFAULT 3 COMMENT '员工性别,子表字段,存储父表id主键值,1=男,2=女,3=保密',
`city` TINYINT UNSIGNED NOT NULL COMMENT '员工所在城市,子表字段,存储父表id主键值,1=北京,2=上海,3=广州,4=重庆,5=天津',
`dep` TINYINT UNSIGNED NOT NULL COMMENT '员工所在部门,子表字段,存储父表id主键值,1=PHP,2=JAVA,3=WEB,4=UI/UE',
`pay` FLOAT(8,2) DEFAULT 5000 COMMENT '员工薪资',
FOREIGN KEY (`sex`) REFERENCES `sexTab`(`id`),
FOREIGN KEY (`city`) REFERENCES `cityTab`(`id`),
FOREIGN KEY (`dep`) REFERENCES `depTab`(`id`)
)ENGINE = InnoDB CHARSET = UTF8 COMMENT '员工信息表,子表结构,存储的是父表的id的主键值';
-- 存储数据
INSERT `use4`(name,age,sex,city,dep,pay)
VALUES
('王卓',21,3,2,1,15000),
('Andy',27,1,3,3,9000),
('半世浮夸',22,1,4,1,6000),
('梁晓洁',17,2,1,4,8000),
('Eric',23,3,1,2,9000),
('echo不开心',21,1,1,1,15000),
('心竹',22,2,5,1,18000),
('执念',20,1,1,1,19000);
-- 联合查询
SELECT u.id,name,age,sexFar,cityFar,depFar,pay FROM `use4` as `u`
INNER JOIN `sexTab` as `s`
ON u.sex = s.id
INNER JOIN cityTab as c
ON u.city = c.id
INNER JOIN depTab as d
ON u.dep = d.id;
```
## 12 无限查询
核心:一个表结构中实现联合查询。
无限极查询就是将传统意义的子表,父表结合为一个表结构。
一级菜单文字内容对应的id主键值,作为二级菜单文字内容的存储数值字段的数据信息。
使用子查询作为父表 `LEFT JOIN`
无限极查询语句:
```sql
SELECT `s`.`id` , `s`.`infName`, `f`.`infName` FROM `inf` as `s`
LEFT JOIN (SELECT `id`,`infName` FROM `inf`) as `f`
ON `s`.`infId` = `f`.`id`;
```
示例:
```sql
-- 创建无限极菜单表结构
-- 至少三个字段
-- id主键值字段
-- 存储菜单文字字段
-- 存储上一级菜单文字对应的id主键值
CREATE TABLE `inf`(
`id` SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT '主键字段',
`infName` VARCHAR(30) NOT NULL COMMENT '字段存储菜单名称',
`infId` SMALLINT UNSIGNED NOT NULL COMMENT '存储上一级菜单名称对应的id主键值'
)ENGINE InnoDB CHARSET UTF8 COMMENT '无限极菜单数据库';
-- 写入数据
-- 从第一级菜单开始,逐级写入菜单名称数据
--
-- 第一级菜单`infName`写对应的文字,`infId`统一写0
INSERT `inf` (`infName`,`infId`) VALUES ('家用电器',0);
INSERT `inf` (`infName`,`infId`) VALUES ('手机',0);
INSERT `inf` (`infName`,`infId`) VALUES ('电脑',0);
--
-- 第一级菜单 家用电器 对应的二级菜单内容
-- `infName` 文字内容
-- `infId` 一级菜单 家用电器 文字id主键值1
INSERT `inf` (`infName`,`infId`) VALUES
('电视',1),
('空调',1),
('洗衣机',1);
--
-- 第三级菜单 二级菜单电视 对应的三级菜单
-- `infName` 文字内容
-- `infId` 二级菜单电视文字id主键值4
INSERT `inf` (`infName`,`infId`) VALUES
('超薄',4),
('全面屏',4),
('智能',4);
--
-- 无限极查询
-- 第一级菜单中,存储的数据为0,没有对应的数据信息,必须使用LEFT JOIN,可以显示为NULL
-- 表子表都是当前无限极表结构`inf`,必须定义别名
-- ON的相互关系: 子表.`infId`=父表.`id`
-- 查询显示SELECT 有来源于父表的字段infName
SELECT s.id, s.infName, f.infName FROM `inf` as s
LEFT JOIN `inf` as f
ON s.infId = f.id;
--
-- 将子查询的结果作为父表
--
-- 父表对于`inf`表结构,只需要id字段,infName字段
SELECT `id`,`infName` FROM `inf`;
--
-- 将子查询作为父表
-- 父表内容减少,提高执行效率
SELECT s.id,s.infName,f.infName FROM inf as s
LEFT JOIN (SELECT `id`,`infName` FROM inf) as f
ON s.infId=f.id;
```
## 数据库的备份(导出)
1, 进入命令行
```txt
win+r 输出 cmd 然后回车
```
2, 执行导出
```txt
mysqldump -u用户名 -p 数据库名称 > 导出文件路径
比如:
mysqldump -uroot -p coding > E:/coding_20200313.sql
```
## 数据库的恢复(导入)
1, 登录MySQL
```txt
mysql [-h主机名] -u用户名 -p 然后回车
```
2, 创建数据库
3, 将备份的文件导入当前创建的数据库
```txt
source E:/coding_20200313.sql
```