目录
[排序:ORDER BY](#排序:ORDER BY)
[GROUP BY字句](#GROUP BY字句)
一、简述
1.MySQL简述
MySQL是一款关系型数据库,是主流开源数据库之一,被广泛应用于各种规模的Web应用、企业系统和嵌入式应用中。
2.SQL简述
SQL是一种专门用于管理和操作关系型数据库的标准化语言,可以让用户存储、操作和检索数据库中数据。
二、数据库操作
1.显示当前数据库
sql
SHOW DATABASES;
2.创建数据库
sql
CREATE DATABASE [IF NOT EXISTS] db_name [create_specification [,create_specification] ...]
create_specification:
[DEFAULT] CHARACTER SET charset_name
[DEFAULT] COLLATE collation_name
说明:
- 大写表示关键字
-
\]是可选项
- COLLATE:指定数据库字符集的校验规则
示例:
- 创建名为db_test的数据库
sql
CREATE DATABASE db_test;
- 如果系统没有db_test的数据库,则创建db_test1的数据库,如果有则不创建
sql
CREATE DATABASE IF NOT EXISTS db_test1;
3.使用数据库
sql
use 数据库名;
4.删除数据库
sql
DROP DATABASE [IF EXISTS] db_name;
三、常用数据类型
1.数值类型(整型和浮点型)
|--------------|------------|-------------------------------|-----------------------------|-------------------------|
| 数据类型 | 大小 | 说明 | 对应java类型 | 具体应用 |
| BIT[(M)] | M指定位数,默认为1 | 二进制数,M范围从1到64,存储数值范围从0到2^M-1 | 常用Boolean对应BIT,此时默认是1位,即0和1 | 开关状态、是否删除标志等 |
| TINYINT | 1字节 | | Byte | 状态标志、枚举数值等 |
| SMALLINT | 2字节 | | Short | 年份等 |
| INT | 4字节 | | Integer | 主键ID、计数器等 |
| BIGINT | 8字节 | | Long | 主键ID(雪花算法)、大数据量、天文数字计数 |
| FLOAT(M,D) | 4字节 | 单精度,M指定长度,D指定小数位数。会发生精度丢失 | Float | 科学实验数据、传感器读数、不需高精度的百分比等 |
| DOUBLE(M,D) | 8字节 | | Double | 地理坐标、物理计算、统计分析中间结果等 |
| DECIMAL(M,D) | M/D最大值+2 | 双精度,M指定长度,D表示小数点位数。精确数值 | BigDecimal | 金额、利率、税率、需固定精度的测量值等 |
| NUMERIC(M,D) | M/D最大值+2 | 和DECIMAL一样 | BigDecimal | 同上 |
2.字符串类型
|---------------|----------------|--------------|----------|--------------------------------|
| 数据类型 | 大小 | 说明 | 对应java类型 | 具体应用 |
| VARCHAR(SIZE) | 0-65535字节 | 可变长度字符串 | String | 用户名、姓名、地址、邮箱、标题、短文本内容、URL等 |
| TEXT | 0-65535字节 | 长文本数据 | String | 文章内容、博客正文、日志内容等 |
| MEDIUMTEXT | 0-16 777 215字节 | 中等长度文本数据 | String | |
| BLOB | 0-65535字节 | 二进制形式的长文本数据库 | String | 文件存储(小文件)、图片/音频/视频二进制、序列化对象存储等 |
3.日期类型
|-----------|-----|-----------------------------|-----------------------------------|------|
| 数据类型 | 大小 | 说明 | 对应java类型 | 具体应用 |
| DATETIME | 8字节 | 范围从1000到9999年,不会进行时区的检索及转换 | java.util.Date、java.sql.Timestamp | |
| TIMESTAMP | 4字节 | 范围从1970到2038年,自动检索当前时区并进行转换 | java.util.Date、java.sql.Timestamp | |
四、表操作
如果需要操作数据库中的表,需要先使用该数据库
sql
use db_test;
1.查看表结构
sql
desc 表名;
示例:

- Field:字段名字
- Type:字段类型
- Null:是否允许为空
- Key:索引类型
- Default:默认值
- Extra:扩充
2.创建表
sql
CREATE TABLE table_name (
field1 datatype,
field2 datatype,
field3 datatype
);
3.删除表
sql
-- 删除 stu_test 表
drop table stu_test;
-- 如果存在 stu_test 表,则删除 stu_test表
drop table if exists stu_test;
五、表的增删改查
示例:准备表及相关数据
sql
-- 创建考试成绩表
DROP TABLE IF EXISTS exam_result;
CREATE TABLE exam_result (
id INT,
name VARCHAR(20),
chinese DECIMAL(3,1),
math DECIMAL(3,1),
english DECIMAL(3,1)
);
sql
INSERT INTO exam_result (id, name, chinese, math, english) VALUES
(1,'唐三藏', 67, 98, 56),
(2,'孙悟空', 87.5, 78, 77),
(3,'猪悟能', 88, 98.5, 90),
(4,'曹孟德', 82, 84, 67),
(5,'刘玄德', 55.5, 85, 45),
(6,'孙权', 70, 73, 78.5),
(7,'宋公明', 75, 65, 30);
1.新增(Create)
sql
INSERT [INTO] table_name
[(column [, column] ...)]
VALUES (value_list) [, (value_list)] ...
value_list: value, [, value] ...
示例:
单行数据 + 全列插入
sql
INSERT INTO exam_result VALUES (8, '唐三藏', 80, 75, 60);
多行数据 + 指定列插入
sql
-- 插入两条记录,value_list 数量必须和指定列数量及顺序一致
INSERT INTO exam_result (id, name, chinese, math, english) VALUES
(9, '曹孟德', 81, 76, 63),
(10, '孙仲谋', 82, 79, 61);
2.查询(Retrieve)
sql
SELECT
[DISTINCT] {* | {colomn [, column] ...}
[FROM table_name]
[WHERE ...]
[ORDER BY column [ASC | DESC], ...]
LIMIT ...
示例:
全列查询
sql
-- 通常情况下不建议使用 * 进行全列查询
-- 1.查询的列越多,意味着需要传输的数据量越大
-- 2.可能影响索引使用
SELECT * FROM exam_result
指定列查询
sql
SELECT id, name, english FROM exam_result
查询字段为表达式
sql
-- 表达式不包含字段
SELECT id, name, 10 FROM exam_result;
-- 表达式包含一个字段
SELECT id, name, english + 10 FROM exam_result;
-- 表达式包含多个字段
SELECT id, name, chinese + math + english FROM exam_result;
别名
sql
SELECT column [AS] alias_name [...] FROM table_name;
sql
-- 结果集中,表头的列名=别名
SELECT id, name, chinese + math + english 总分 FROM exam_result;
去重:DISTINCT
sql
-- 例如数据有80,80,62,72,54,70
-- 去重后查出80,62,72,54,70
SELECT DISTINCT math FROM exam_result;
排序:ORDER BY
sql
-- ASC 升序(从小到大)
-- DESC 降序(从大到小)
-- 默认 ASC
SELECT ... FROM table_name [WHERE ...]
ORDER BY column [ASC|DESC], [...];
条件查询:WHERE
比较运算符:
|-------------------|--------------------------------------------|
| 运算符 | 说明 |
| >,>=,<,<= | 大于,大于等于,小于,小于等于 |
| = | 等于,NULL不安全,例如NULL=NULL的结果是NULL |
| <=> | 等于,NULL安全,例如NULL<=>NULL的结果是TRUE(1) |
| !=,<> | 不等于 |
| BETWEEN a0 AND a1 | 范围匹配,[a0,a1],如果a0<=value<=a1,返回TRUE(1) |
| IN(option,...) | 如果是option中的任意一个,返回TRUE(1) |
| IS NULL | 是NULL |
| IS NOT NULL | 不是NULL |
| LIKE | 模糊匹配。%表示任意多个(包括0个)任意字符;_表示任意一个字符 |
逻辑运算符:
|-----|-----------------------------|
| 运算符 | 说明 |
| AND | 多个条件必须都为TRUE(1),结果才是TRUE(1) |
| OR | 任意一个条件为TURE(1),结果为TRUE(1) |
| NOT | 条件为TURE(1),结果为FALSE(0) |
分页查询:LIMIT
sql
-- 起始下标为0
-- 从0开始,筛选n条结果
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT n;
-- 从s开始,筛选n条结果
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT s, n;
-- 同上
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT m OFFSET s;
示例:按id分页,每页3条记录,分别显示第1、2、3页
sql
-- 第 1 页
SELECT id, name, math, english, chinese FROM exam_result ORDER BY id LIMIT 3 OFFSET 0;
-- 第 2 页
SELECT id, name, math, english, chinese FROM exam_result ORDER BY id LIMIT 3 OFFSET 3;
-- 第 3 页
SELECT id, name, math, english, chinese FROM exam_result ORDER BY id LIMIT 3 OFFSET 6;
3.修改(Update)
sql
UPDATE table_name SET column = expr [, column = expr ...]
[WHERE ...] [ORDER BY ...] [LIMIT ...]
示例:
sql
-- 将曹孟德同学的数学成绩变更为 89 分
UPDATE exam_result SET math = 89 WHERE name = '曹孟德';
-- 将孙悟空同学的数学成绩变更为 10 分, 语文成绩变更为 20 分
UPDATE exam_result SET math = 10, chinese = 20 WHERE name = '孙悟空';
-- 将总成绩倒数前三的 3 位同学的数学成绩加上30分
UPDATE exam_result SET math = math + 30 ORDER BY chinese + math + english LIMIT 3;
-- 将所有同学的语文成绩更新为原来的 2 倍
UPDATE exam_result SET chinese = chinese * 2;
4.删除(Delete)
sql
DELETE FROM table_name [WHERE ...] [ORDER BY ...] [LIMIT ...]
示例:
sql
-- 删除孙悟空同学的考试成绩
DELETE FROM exam_result WHERE name = '孙悟空';
-- 删除整张表数据
-- 准备测试表
DROP TABLE IF EXISTS for_delete;
CREATE TABLE for_delete (
id INT,
name VARCHAR(20)
);
-- 插入测试数据
INSERT INFO for_delete (name) VALUES ('A'), ('B'), ('C');
-- 删除整表数据
DELETE FROM for_delete;
六、数据库约束
约束类型
|-------------|----------------------------------------------------------|
| 类型 | 说明 |
| NOT NULL | 某列不能存储NULL值 |
| UNIQUE | 保证某列的每行必须有唯一值 |
| DEFAULT | 规定没有给列赋值时的默认值 |
| PRIMARY KEY | NOT NULL + UNIQUE 确保某列(或多列的结合)有唯一标识,有助于更容易更快速找到表中的一个特定记录 |
| FOREIGN KEY | 保证一个表中数据匹配另一个表中的值得参照完整性 |
| CHECK | 保证列中的值符合指定的条件。对于MySQL数据库,对CHECK字句进行分析,但是忽略CHECK字句 |
七、表的设计
三大范式
1.一对一

2.一对多

3.多对多

八、查询
1.聚合查询
常见聚合函数
|--------------------------|----------------------|
| 函数 | 说明 |
| COUNT([DISTINCT] expr) | 返回查询到的数据的数量 |
| SUM([DISTINCT] expr) | 返回查询到的数据的总和,不是数字没有意义 |
| AVG([DISTINCT] expr) | 返回查询到的数据平均值,不是数字没有意义 |
| MAX([DISTINCT] expr) | 返回查询到的数据最大值,不是数字没有意义 |
| MIN([DISTINCT] expr) | 返回查询到的数据最小值,不是数字没有意义 |
示例:
sql
-- COUNT
-- 统计班级学生数量
SELECT COUNT(*) FROM student;
-- 统计班级收集的 qq_mail 有多少个,为 NULL 的数据不会计入结果
SELECT COUNT(qq_mail) FROM student;
-- SUM
-- 统计数学成绩总分
SELECT SUM(math) FROM exam_result;
-- AVG
-- 统计平均总分
SELECT AVG(chinese + math + english) 平均总分 FROM exam_result;
-- MAX
-- 返回英语最高分
SELECT MAX(english) FROM exam_result;
-- MIN
-- 返回 > 70 分以上的数学最低分
SELECT MIN(math) FROM exam_result WHERE math > 70;
GROUP BY字句
SELECT中使用GROUP BY字句可以对指定列进行分组查询
需满足:使用GROUP BY进行分组查询时,SELECT指定的字段必须是"分组依据字段",其他字段若想出现在SELECT中则必须包含在聚合函数中。
ruby
SELECT column1, SUM(column2), ... FROM table GROUP BY column1;
示例:
sql
-- 查询每个角色的最高工资、最低工资和平均工资
SELECT role, MAX(salary), MIN(salary), AVG(salary) FROM emp GROUP BY role;
HAVING
GROUP BY字句进行分组后,需要对分组结果再进行条件过滤时,不能使用WHERE语句,而需要使用HAVING
sql
-- 显示平均工资低于1500的角色和他的平均工资
SELECT role, MAX(salary), MIN(salary), AVG(salary) FROM emp GROUP BY role
HAVING AVG(salary) < 1500;
2.联合查询
开发中数据可能来自不同的表,所以需要多表联合查询。多表查询是对多张表的数据取笛卡尔积
关联查询可以对关联表使用别名
内连接
sql
SELECT 字段 FROM 表1 别名1 [inner] join 表2 别名2 on 连接条件 and 其他条件;
SELECT 字段 FROM 表1 别名1, 表名2 别名2 WHERE 连接条件 AND 其他条件;
示例:
sql
-- 查询"小明"的成绩
SELECT sco.score FROM student stu INNER JOIN score sco ON stu.id = sco.student_id
AND stu.name = '小明';
-- 或
SELECT sco.score FROM student stu, score sco WHERE stu.id = sco.student_id
AND stu.name = '小明';
-- 成绩表对学生表示多对1关系, 查询总成绩是根据成绩表的同学id来进行分组的
SELECT
stu.sn,
stu.name,
stu.qq_mail,
sum(sco.score),
FROM
student stu
JOIN score sco ON stu.id = sco.student_id
GROUP BY
sco.student_id;
-- 查询所有同学的成绩, 及同学的个人信息
SELECT * FROM student stu join score sco ON stu.id = sco.student_id;
-- 学生表、成绩表、课程表联查
SELECT
stu.id,
stu.sn,
stu.name,
stu.qq_mail,
sco.score,
sco.course_id,
cou.name
FROM
student stu
JOIN score sco ON stu.id = sco.student_id
JOIN course cou ON sco.course_id = cou.id
ORDER BY
stu.id;
外连接
外连接分为左外连接和右外连接。左侧表完全显示即左外连接,右侧的表完全显示即右外连接
sql
-- 左外
SELECT 字段名 FROM 表名1 LEFT JOIN 表名2 ON 连接条件;
-- 右外
SELECT 字段名 FROM 表名1 RIGHT JOIN 表名2 ON 连接条件;
示例:
sql
-- 查询所有同学的成绩, 及同学的个人信息, 如果该同学没有成绩, 也需要显示
SELECT * FROM student stu LEFT JOIN score sco ON stu.id = sco.student_id;
SELECT * FROM score sco RIGHT JOIN student stu ON stu.id = sco.student_id;
自连接
在同一张表连接自身进行连接
sql
-- 显示所有"计算机组成原理"成绩比"数据结构"成绩高的成绩信息
-- 先查询课程id
SELECT id, name FROM course WHERE name = '计算机组成原理' or name = '数据结构';
SELECT
s1.*
FROM
score s1,
score s2
WHERE
s1.student_id = s2.student_id
AND s1.score < s2.score
AND s1.course_id = 1
AND s2.course_id = 3;
子查询
其他sql语句中的select语句,也叫嵌套查询
sql
-- 单行子查询:返回一行记录的子查询
-- 查询与"小明"的同班同学
SELECT * FROM student WHERE classes_id = (SELECT classes_id FROM student WHERE
name = '小明');
-- 多行子查询:返回多行记录的子查询
-- 查询"语文"或"英文"课程的成绩信息
-- [NOT] IN 关键字
SELECT * FROM score WHERE course_id IN (SELECT id FROM course WHERE
name = '语文' or name = '英文');
合并查询
合并多个select的执行结果,可以使用集合操作符 union,union all 使用UNION和UNION ALL 时,前后查询的结果集中,字段需要一致
sql
-- union
-- 该操作符用于取得两个结果集的并集,会自动去掉结果集中的重复行
-- 示例:查询id小于3, 或者名字为"英文"的课程
SELECT * FROM course WHERE id < 3
UNION
SELECT * FROM course WHERE name = '英文';
-- union all
-- 该操作符用于取得两个结果集的并集,不会去掉重复行
-- 示例:查询id小于3, 或者名字为"数据结构"的课程
SELECT * FROM course WHERE id < 3
UNION
SELECT * FROM course WHERE name = '数据结构'