- MySQL配置文件(my.cnf 或 my.ini) 一般位于
/etc/mysql/
或/etc/
目录下。 - MySQL 数据目录 默认情况下是在
/var/lib/mysql/
,这里存放了数据库的数据文件。 - 我安装的mysql
- ip: 192.168.31.20
- port: 3306
- 用户名: root, mysql8_gtc
- 密码: ROOT, gtc123
第一章: 基础篇
1. 数据类型
1.1 数值类型

1.2 字符串类型

1.3 日期时间类型

2. SQL
2.1 SQL分类
|-----|----------------------------|--------------------------------------|
| 分类 | 全称 | 说明 |
| DDL | Data Definition Language | 数据定义语言, 用来定义数据库 ,表 和字段 |
| DML | Data Manipulation Language | 数据操作语言,用来对数据库表中的数据进行增删改 |
| DQL | Data Query Language | 数据查询语言,用来查询数据库中表的记录 |
| DCL | Data Control Language | 数据控制语言,用来创建数据库用户 ,控制数据库的访问权限 |
2.2 DDL
DDL用来定义,删除和修改数据库 ,表 和字段。
2.2.1 DDL操作数据库
-
查询所有数据库
sqlSHOW DATABASES;
-
查询当前所处数据库
sqlSELECT DATABASES();
-
创建数据库
sqlCREATE DATABASE [IF NOT EXISTS] 数据库名 [DEFAULT CHARSET 字符集] [COLLATE 排序规则]
-
删除数据库
sqlDROP DATABASE [IF EXISTS] 数据库名;
-
使用数据库
sqlUSE 数据库名;
2.2.2 DDL操作表
-
查询当前数据库所有表
sqlSHOW TABLES;
-
查询表结构
sqlDESC 表名;
-
查询指定表的建表语句
sqlSHOW CREATE TABLE 表名;
-
创建表
sqlCREATE TABLE 表名( 字段1 字段1类型 [COMMENT 字段1注释], 字段2 字段1类型 [COMMENT 字段2注释], 字段3 字段1类型 [COMMENT 字段3注释], ...... 字段n 字段1类型 [COMMENT 字段n注释] ) [COMMENT 表注释];
-
修改表
sql-- 添加字段 ALTER TABLE 表名 ADD 字段名 字段类型(长度) [COMMENT 注释] [约束]; -- 修改数据类型 ALTER TABLE 表名 MODIFY 字段名 新数据类型(长度); -- 修改字段名和字段类型 ALTER TABLE 表名 CHANGE 旧字段名 新字段名 类型(长度) [COMMENT 注释] [约束]; -- 修改表名 ALTER TABLE 表名 RENAME TO 新表名;
-
删除表
sql-- 删除表 DROP TABLE [IF EXISTS] 表名; -- 删除指定表,并重新创建该表 TRUNCATE TABLE 表名; -- DROP删除表的数据+表的结构,而TRUNCATE只删除表的数据,不删除表的结构
选择使用 DROP TABLE
还是 TRUNCATE TABLE
应基于你是否希望保留表结构以及你需要执行的具体操作类型。如果你只是想清空表内的数据并保留表结构,TRUNCATE TABLE
是更合适的选择。如果你不再需要这个表及其数据,则应使用 DROP TABLE
。
2.3 DML
DML用来对数据库中表的记录进行增删改操作。
2.3.1 增加-INSERT
-
给指定字段添加数据
sqlINSERT INTO 表名(字段1, 字段2, ...) VALUES(值1, 值2, ...);
-
给全部字段添加数据
sqlINSERT INTO 表名 VALUES (值1, 值2, ...);
-
批量添加数据
sql-- 批量添加指定字段 INSERT INTO 表名(字段1, 字段2, ...) VALUES (值1, 值2, ...), (值1, 值2, ...), (值1, 值2, ...); -- 批量添加全部字段 INSERT INTO 表名 VALUES (值1, 值2, ...), (值1, 值2, ...), (值1, 值2, ...);
-
注意:
- 插入数据时,指定的字段顺序需要与值的顺序是一一对应的。
- 字符串和日期数据应该包括在引号中。
- 插入的数据大小,应该在字段的规定范围内。
2.3.2 修改-UPDATE
-
修改数据
sqlUPDATE 表名 SET 字段名1=值1, 字段名2=值2, ... [WHERE 条件];
注意:修改语句的条件可以有,也可以没有,如果没有条件,则会修改整张表的所有数据。
2.3.3 删除-DELETE
-
删除数据
sqlDELETE FROM 表名 [WHERE 条件];
注意:DELETE语句的条件可以有,也可以没有,如果没有条件,则会删除整张表的所有数据。DELETE语句是按照行删除的,不能删除某一个字段的值(可以使用UPDATE)
2.4 DQL
2.4.1 单表查询

(1)基础查询
- 查询多个字段
sql
-- 查询指定字段
SELECT 字段1, 字段2, 字段3, ... FROM 表名;
-- 查询所有字段
SELECT * FROM 表名;
- 设置别名
sql
SELECT 字段1 [AS 别名1], 字段2 [AS 别名2], ... FROM 表名;
- 去除重复记录
sql
SELECT DISTINCT 字段列表 FROM 表名;
(2)条件查询
- 语法
sql
SELECT 字段列表 FROM 表名 WHERE 条件列表;
- 条件
|---------------------|------------------------|
| 比较运算符 | 功能 |
| > | 大于 |
| >= | 大于等于 |
| < | 小于 |
| <= | 小于等于 |
| = | 等于 |
| <>或!= | 不等于 |
| BETWEEN ... AND ... | 在某个范围之内(含最大,最小值) |
| IN(...) | 在in之后的列表中的值, 多选一 |
| LIKE 占位符 | 模糊匹配(_是单个字符, %匹配任意个字符) |
| IS NULL | 是NULL |
|------------|----------------|
| 逻辑运算符 | 功能 |
| AND 或 && | 并且(多个条件同时成立) |
| OR 或 || | 或者(多个条件任意一个成立) |
| NOT 或 ! | 非 |
(3)聚合函数
- 介绍:将一列数据作为一个整体,进行纵向计算。注意:NULL值不参与运算
- 常见聚合函数
- count:统计数量
- max:统计最大值
- min:统计最小值
- avg:平均值
- sum:求和
- 语法
sql
SELECT 聚合函数(字段列表) FROM 表名;
(4)分组查询⭐️⭐️⭐️
分组查询 === 一组一行数据 === 聚合函数也是得到一行数据
分组查询使用的关键字是GROUP BY,通常要和聚合函数与HAVING一起。SELECT 列表中的所有字段,要么是 GROUP BY 中出现的字段,要么必须是聚合函数(如 MAX、MIN、COUNT、SUM 等)的参数。
GROUP BY
子句在 SQL 查询中并不强制要求与聚合函数一起使用,但通常情况下它们是搭配使用的。这是因为 GROUP BY
的主要作用是将数据按照一个或多个列的值进行分组,而聚合函数(如 COUNT()
, SUM()
, AVG()
, MAX()
, MIN()
等)则用于对每个分组计算汇总值。
- 语法
sql
SELECT 字段列表 FROM 表名 [WHERE 条件] GROUP BY 分组字段名 [HAVING 分组后过滤条件];
- where和having区别
- 执行时机不同:where是分组之前进行过滤,不满足where条件不参与分组;而having是分组之后对结果进行过滤。
- 判断条件不同:where不能对聚合函数进行判断,而having可以。
分组查询案例:
有如下一个部门表:

分析执行:
sql
select deptno,sum(sal) AS total from employee where sal>1000 group by deptno having sum(sal) >9000
order by sum(sal) asc;
分析过程:
该SQL的书写顺序:
select, from, where, group by, having, order by
实际的执行顺序:
from, where, group by, having, select, order by
一: 执行from employee
sql
select * from employee;

二: 执行where sal > 1000
sql
select * from employee where sal > 1000;

三: 执行group by deptno
sql
select deptno from employee where sal > 1000 group by deptno;

四: 执行having sum(sal) > 9000
对每个分组,分别求sum(sal),只有sum(sal) > 9000 的分组才会显示。

五: 执行select deptno, sum(sal) as total
计算每个分组的sum(sal)

六: 执行order by
(5)排序查询
- 语法
sql
SELECT 字段列表 FROM 表名 ORDER BY 字段1 排序方式1, 字段2 排序方式2;
- 排序方式
- ASC:升序(默认)
- DESC:降序
- 注意:如果是多字段排序,当第一个字段值相同时,才会根据第二个字段进行排序。
(6)分页查询
- 语法
sql
SELECT 字段列表 FROM 表名 LIMIT 起始索引, 查询记录数;
- 注意
- 起始索引从0开始,起始索引 = (查询页码 - 1) * 每页显示记录数
- 分页查询是数据库的方言,不同的数据库有不同的实现,MySQL中是LIMIT
- 如果查询的是第一页数据,起始索引可以省略,直接简写为limit 10
(7)执行顺序⭐️⭐️⭐️
- 书写顺序
- select
- from
- where
- group by
- having
- order by
- limit
- 执行顺序
- from -- 行过滤
- where
- group by
- having
- select -- 列过滤
- order by
- limit
一句话:select在分组查询group by ... having ...之后。
where是分组之前过滤,having是分组之后过滤。
2.4.2 多表查询
多表查询见第5小节: 多表查询。
2.5 DCL
DCL是数据控制语言,用来管理数据库用户 和控制数据库的访问权限。
2.5.1 DCL用户管理
(1)查询用户
sql
USE mysql;
SELECT * FROM user;
mysql中,用户信息保存在mysql数据库的user表里。

(2)创建用户
sql
CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';
(3)修改用户密码
sql
ALTER USER '用户名'@'主机名' IDENTIFIED WITH mysql_native_password BY '新密码';
(4)删除用户
sql
DROP USER '用户名'@'主机名';
案例:
sql
-- 创建用户itcast, 只能够在当前主机localhost访问, 密码123456
create user 'itcast'@'localhost' identified by '123456';
-- 创建用户heima, 可以在任意主机访问该数据库, 密码123456
create user 'heima'@'%' identified by '123456';
-- 修改用户heima的访问密码 1234;
alter user 'heima'@'%' identified with mysql_native_password by '1234';
-- 删除itcast@localhost用户
drop user 'itcast'@'localhost';
注意:
- 主机名可以使用%通配
- 这类SQL开发人员操作的比较少,主要是DBA(Database Administrator数据库管理员)使用。
2.5.2 DCL权限控制
mysql数据库可以被不同用户登陆,但是不同用户对于数据库的操作权限可能不一样。
权限: mysql登陆用户操作某数据库的权限。
|---------------------|------------|
| 权限 | 说明 |
| ALL, ALL PRIVILEGES | 所有权限 |
| SELECT | 查询数据 |
| INSERT | 插入数据 |
| UPDATE | 更新数据 |
| DELETE | 删除数据 |
| ALTER | 修改表 |
| DROP | 删除数据库/表/视图 |
| CREATE | 创建数据库/表 |
(1)查询权限
sql
SHOW GRANTS FOR '用户名'@'主机名';
(2)授予权限
sql
GRANT 权限列表 ON 数据库名.表名 TO '用户名'@'主机名';
(3)撤销权限
sql
REVOKE 权限列表 ON 数据库.表名 FROM '用户名'@'主机名';
3. 函数
函数 是指一段可以直接被另一段程序调用的程序或代码。函数是mysql内置的。
3.1 字符串函数
|----------------------------|--------------------------------------|
| 函数 | 功能 |
| CONCAT(s1,s2,...) | 字符串拼接 |
| LOWER(str) | 将字符串str全部转为小写 |
| UPPER(str) | 将字符串str全部转为大写 |
| LPAD(str, n, pad) | 左填充, 用字符串pad对str的左边进行填充, 达到n个字符串长度 |
| RPAD(str, n, pad) | 右填充, 用字符串pad对str的左、右边进行填充, 达到n个字符串长度 |
| TRIM(str) | 去掉字符串头部和尾部的空格 |
| SUBSTRING(str, start, len) | 返回从字符串str从start位置起的len个长度的字符串 |
[Mysql常用内置字符串函数]
案例:
sql
SELECT CONCAT('Hello', ' MySQL'); -- 得到'Hello MySQL'
SELECT LOWER('Hello'); -- 得到'hello'
SELECT UPPER('Hello'); -- 得到'HELLO'
SELECT LPAD('01',5,'-'); -- 得到'---01'
SELECT RPAD('01',5,'-'); -- 得到'01---'
SELECT TRIM(' Hello MySQL ') -- 得到'Hello MySQL'
SELECT SUBSTRING('Hello MySQL',1,5); -- 得到'Hello'
3.2 数值函数
|------------|--------------------|
| 函数 | 功能 |
| CEIL(x) | 向上取整 |
| FLOOR(x) | 向下取整 |
| MOD(x,y) | 返回x/y的模 |
| RAND() | 返回0~1内的随机数 |
| ROUND(x,y) | 求参数x的四舍五入的值,保留y位小数 |
3.3 日期函数
|------------------------------------|----------------------------|
| 函数 | 功能 |
| CURDATE() | 返回当前日期 |
| CURTIME() | 返回当前时间 |
| NOW() | 返回当前日期和时间 |
| YEAE(date) | 获取指定date的年份 |
| MONTH(date) | 获取指定date的月份 |
| DAY(date) | 获取指定date的日期 |
| DATE_ADD(date, INTERVAL expr type) | 返回一个日期/时间加上一个时间间隔expr后的时间值 |
| DATEDIFF(date1, date2) | 返回起始时间date1和结束时间date2之间的天数 |
3.4 流程函数
|--------------------------------------------------------------------|----------------------------------------|
| 函数 | 功能 |
| IF(value, t, f) | 如果value为true,则返回t,否则返回f |
| IFNULL(value1, value2) | 如果value==null,返回value2,否则返回value1 |
| CASE WHEN [val1] THEN [res1] ... ELSE [default] END | 如果val1为true, 返回res1, ...否则返回default默认值 |
| CASE [expr] WHEN [val1] THEN [res1] ... ELSE [default] END | 如果expr的值等于val1,返回res1,否则返回default默认值 |
4. 约束
4.1 约束概述
概念:约束是作用于表中字段上的规则,用于限制存储在表中的数据;
目的:保证数据库中数据的正确,有效和完整性。
4.2 约束的分类
|------------------|------------------------------|-------------|
| 约束 | 描述 | 关键字 |
| 非空约束 | 限制该字段的数据不能为null | NOT NULL |
| 唯一约束 | 保证该字段的所有数据都是唯一,不重复的 | UNIQUE |
| 默认约束 | 保存数据时,如果未指定该字段的值,则采用默认值 | DEFAULT |
| 主键约束 | 主键是一行数据的唯一标识,要求非空且唯一 | PRIMARY KEY |
| 外键约束 | 用来让两张表的数据之间建立连接,保证数据的一致性和完整性 | FOREIGN KEY |
| 检查约束(8.0.16版本之后) | 保证字段值满足某一个条件 | CHECK |
注意:约束是作用于表中字段上的,可以在创建表/修改表的时候添加约束。
4.3 约束演示
根据需求,完成表结构的创建。
|---------|----------|-------------|---------------|----------------------------|
| 字段名 | 字段含义 | 字段类型 | 约束条件 | 约束关键字 |
| id | ID唯一标识 | int | 主键,并且自动增长 | PRIMARY KEY,AUTO_INCREMENT |
| name | 姓名 | varchar(10) | 不为空,并且唯一 | NOT NULL,UNIQUE |
| age | 年龄 | int | 大于0,并且小于等于120 | CHECK |
| status | 状态 | char(1) | 如果没有指定该值,默认为1 | DEFAULT |
| gender | 性别 | char(1) | 无 | |
sql
CREATE TABLE user(
id int PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
name VARCHAR(10) NOT NULL UNIQUE COMMENT '姓名',
age INT CHECK (age > 0 && age <= 120) COMMENT '年龄',
status CHAR(1) DEFAULT('1') COMMENT '状态',
gender CHAR(1) COMMENT '性别'
) COMMENT '用户表';
4.4 外键约束
4.4.1 概念
外键用来让两张表的数据之间建立连接,从而保证数据的一致性和完整性。

注意:目前上述的两张表,在数据库层面,并没有建立外键关联,所以是无法保证数据的一致性和完整性。
4.4.2 外键的建立
- 添加外键
sql
-- 第一种方式
CREATE TABLE 表名(
字段名 数据类型,
...
[CONSTRAINT] [外键名称] FOREIGN KEY(外键字段名) REFERENCES 主表(主表列名)
);
-- 第二种方式
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY(外键字段名) REFERENCES 主表(主表列名);

当dept_id被设置为外键之后,再去删除dept表的'1研发部'就无法成功删除(因为emp表里还存在dept_id=1的员工)
- 删除外键
sql
ALTER TABLE 表名 DROP FOREIGN KEY 外键;
4.4.3 外键删除/更新行为
|-------------|--------------------------------------------------------------------|
| 行为 | 说明 |
| NO ACTION | 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除/更新。 |
| RESTRICT | 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除/更新。 |
| CASCADE | 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则删除/更新在子表中的记录。 |
| SET NULL | 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则设置子表中该外键值为null(这就要求该外键允许取null)。 |
| SET DEFAULT | 父表有变更时,子表将外键列设置成一个默认的值(InnoDB不支持) |
sql
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY(外键字段名) REFERENCES 主表(主表列名) ON UPDATE CASCADE ON DELETE CASCADE;
执行这条语句后,若删除dept表id=1的研发部,则emp表中dept_id=1的数据也会删除。
5. 多表查询
前面讲了单表查询的DQL,这一节讲解多表查询的DQL。
5.1 多表关系
5.1.1 一对多
- 案例:部门与员工的关系
- 关系:一个部门可以有多个员工,一个员工对应一个部门
- 实现:在多的一方建立外键,指向一的一方的主键

5.1.2 多对多
- 案例:学生与课程的关系
- 关系:一个学生可以选择多个课程,一个课程也可以被多个学生选择
- 实现:建立第三章中间表,中间表至少包含两个外键,分别关联两方主键

5.1.3 一对一
- 案例:用户与用户详情的关系
- 关系:一对一关系,多用于单表拆分,将一张表的基础字段放在一张表中,其他详情字段放在另一张表中,以提升操作效率。
- 实现:在任意一方加入外键,关联另外一方的主键,并且设置外键为唯一的(UNIQUE)

5.2 多表查询概述
- 概述:指从多张表中查询数据
- 笛卡尔积:笛卡尔乘积是指在数学中,两个集合A集合和B集合的所有组合情况。(在多表查询时,需要消除无效的笛卡尔积)。

笛卡尔积演示:
sql
SELECT * FROM emp, dept;
消除上述笛卡尔积(隐式内连接):
sql
SELECT * FROM emp, dept WHERE emp.dept_id = dept.id;
5.3 多表查询分类
- 连接查询
- 内连接:查询A, B交集部分数据
- 外连接
- 左外连接:查询左表所有数据,以及两张表交集部分数据
- 右外连接:查询右表所有数据,以及两张表交集部分数据
- 自连接:当前表与自身的连接查询,自连接必须使用表别名
- 子查询
5.4 内连接
内连接:查询A, B交集部分数据
- 隐式内连接
sql
SELECT 字段列表 FROM 表1, 表2 WHERE 条件 ...;
- 显式内连接
sql
SELECT 字段列表 FROM 表1 [INNER] JOIN 表2 ON 连接条件 ...;

5.5 外连接
- 左外连接:表1所有数据+表2部分数据
sql
SELECT 字段列表 FROM 表1 LEFT [OUTER] JOIN 表2 条件...;
- 右外连接:表2所有数据+表1部分数据
sql
SELECT 字段列表 FROM 表1 RIGHT [OUTER] JOIN 表2 条件...;
5.6 自连接
sql
SELECT 字段列表 FROM 表A 别名A JOIN 表A 别名B ON 条件...;
自连接查询,可以是内连接查询,也可以是外连接查询。
5.7 联合查询union
对于union查询,就是把多次查询的结果合并起来,形成一个新的查询结果集。
sql
SELECT 字段列表 FROM 表A ...
UNION [ALL]
SELECT 字段列表 FROM 表B ...;
对于联合查询的多张表的列数必须保持一致,字段类型也需要保持一致。