本文档基于实际 sql 练习代码,系统梳理 mysql 的核心知识点,涵盖 sql 语言分类、数据定义(ddl)、数据操作(dml)、数据查询(dql)三大核心领域,并对每个知识点进行拓展和补充,帮助读者建立完整的 mysql 知识体系。
一、sql 语言分类总览
sql(structured query language,结构化查询语言)按照功能不同,可分为五大类:
| 分类 | 全称 | 核心命令 | 说明 |
|---|---|---|---|
| dql | data query language(数据查询语言) | select | 对数据进行查询,是使用频率最高的命令 |
| dml | data manipulation language(数据操作语言) | insert、update、delete | 对数据进行增、删、改操作 |
| ddl | data definition language(数据定义语言) | create、alter、drop | 对数据库结构进行定义和修改 |
| dcl | data control language(数据控制语言) | grant、revoke | 对数据库进行权限管理 |
| tcl | transaction control language(事务控制语言) | commit、rollback、savepoint | 对事务进行管理 |
学习建议:重点掌握 ddl、dml、dql 三类,它们构成了日常开发中 95% 以上的 sql 操作。
二、ddl — 数据定义语言
ddl 负责定义和修改数据库的结构,包括创建表、修改表结构、删除表等操作。
2.1 创建表(create)
create table testd(
id int primary key auto_increment,
company varchar(100),
name varchar(100),
age smallint,
email varchar(100)
);
关键语法说明:
primary key:主键约束,保证字段唯一且不为空auto_increment:自增字段,插入数据时无需手动赋值varchar(n):可变长度字符串,n为最大字符数int、smallint:整数类型,smallint取值范围更小(-32768 ~ 32767)
2.2 修改表结构(alter)
alter 是表结构修改的利器,支持多种操作:
-- 添加字段 alter table test2 add gender varchar(10); -- 修改字段类型 alter table test2 modify age smallint; -- 删除字段 alter table test2 drop column gender; -- 重命名表 alter table test2 rename to testz;
拓展知识:
| 操作 | 语法 | 说明 |
|---|---|---|
| 添加字段 | alter table 表名 add 字段名 类型 | 默认添加到表末尾 |
| 修改字段类型 | alter table 表名 modify 字段名 新类型 | 仅改类型,不改字段名 |
| 修改字段名+类型 | alter table 表名 change 旧名 新名 新类型 | change 可同时改名字和类型 |
| 删除字段 | alter table 表名 drop column 字段名 | 注意:删除后数据不可恢复 |
| 重命名表 | alter table 表名 rename to 新表名 | 或使用 rename table 旧名 to 新名 |
2.3 删除表(drop)
-- 删除指定表 drop table testd;
注意事项:
drop table会删除表结构和所有数据,且不可恢复- 如果只想清空数据但保留表结构,使用
truncate table或delete from truncate比delete效率更高,且重置自增计数器
2.4 查看建表语句
show create table testz;
该命令可以查看某张表的完整建表 sql 语句,在迁移表结构时非常有用。
三、dml — 数据操作语言
dml 负责对数据进行增、删、改操作,是日常开发中最频繁使用的操作之一。
3.1 插入数据(insert)
-- 插入指定字段的值
insert into test2(name, age) values("赵六", null);要点:
- 可指定部分字段,未指定的字段使用默认值或
null - 字符串使用引号包裹,mysql 中支持单引号
'和双引号" null表示空值,与空字符串""是不同的概念
3.2 更新数据(update)
-- 更新单条数据 update test2 set age = 29 where name = "张三"; -- 更新多条数据(同时修改多个字段) update 表名 set 字段1 = 值1, 字段2 = 值2 where 条件;
⚠️ 重要提醒:
- 必须带 where 条件! 不带 where 会更新全表所有数据
- 推荐在执行前先用
select确认受影响的数据范围
3.3 删除数据(delete)
-- 删除指定数据 delete from test2 where name = "张八" and age = 19;
delete vs truncate vs drop:
| 命令 | 作用 | 可回滚 | 重置自增 | 效率 |
|---|---|---|---|---|
delete from 表 where 条件 | 删除满足条件的数据 | ✅ 是(在事务中) | ❌ 否 | 逐行删除,较慢 |
truncate table 表 | 清空表所有数据 | ❌ 否 | ✅ 是 | 快速,直接重置 |
drop table 表 | 删除表结构和数据 | ❌ 否 | — | 最快 |
四、dql — 数据查询语言
dql 是 sql 中最强大、最常用的部分,select 语句支持丰富的查询方式。
4.1 基础查询
-- 查询所有字段 select * from test2; -- 查询指定字段 select name, age from test2;
建议:避免使用 select *,明确指定需要的字段可以:
- 减少数据传输量
- 提高查询效率
- 便于代码维护
4.2 条件查询(where)
-- 单条件查询 select name, age from test2 where age > 20; -- 等值查询 select name, age from test2 where name = "王五"; -- 多条件组合查询(and / or) select * from test2 where name like "%张%" and age > 15;
常用比较运算符:
| 运算符 | 含义 | 示例 |
|---|---|---|
= | 等于 | where name = '张三' |
!= / <> | 不等于 | where age != 20 |
>, <, >=, <= | 大小比较 | where age > 20 |
between ... and | 范围查询 | where age between 24 and 25 |
in (...) | 多值查询 | where name in ('张三', '王五') |
like | 模糊查询 | where name like '%张%' |
is null | 为空判断 | where age is null |
is not null | 非空判断 | where age is not null |
4.3 模糊查询(like)
-- 模糊查询:匹配包含"张"的名字 select name, age from test2 where name like "%张%";
like 通配符说明:
| 通配符 | 含义 | 示例 |
|---|---|---|
% | 匹配任意长度的任意字符 | '%张%' 表示包含"张" |
_ | 匹配单个任意字符 | '张_' 表示以"张"开头的两字符字符串 |
'张%' | 以"张"开头 | — |
'%张' | 以"张"结尾 | — |
4.4 范围查询(between and)
-- 查询年龄在 24 到 25 之间的数据(包含边界值) select * from testz where age between 24 and 25;
between a and b 等价于 >= a and <= b,包含边界值。
4.5 多值查询(in)
-- 查询 name 是张三或王五的记录
select * from test2 where name in("张三", "王五");
in 的优势:当需要匹配多个值时,in 比多个 or 更简洁,且性能更优。
4.6 null 值处理
-- 查询年龄为空的数据 select name, age from test2 where age is null; -- 查询年龄不为空的记录 select * from test2 where age is not null;
⚠️ 注意:判断 null 必须使用 is null / is not null,不能使用 = 或 !=。
4.7 排序与限制
-- 按 id 降序排列,取前 10 条 select * from test2 order by id desc limit 10;
常用排序方式:
| 语法 | 含义 |
|---|---|
order by 字段 asc | 升序排列(默认) |
order by 字段 desc | 降序排列 |
order by 字段1 asc, 字段2 desc | 多字段排序 |
limit n | 取前 n 条 |
limit offset, n | 从第 offset 条开始取 n 条(分页场景) |
4.8 去重查询(distinct)
-- 单列去重 select distinct name from test2; -- 多列组合去重:只有 name 和 age 都相同才会去重 select distinct name, age from testz;
关键理解:distinct 不是只修饰紧跟其后的字段,而是对 所有 select 后面的字段整体组合 进行去重。
五、聚合函数
聚合函数对一组数据进行计算,返回单一的值。
5.1 常用聚合函数
-- 统计总记录数 select count(*) from test2; -- 统计某字段非空的记录数 select count(age) from test2; -- 查询平均年龄 select avg(age) from test2; -- 查询最大年龄 select max(age) from test2; -- 查询最小年龄 select min(age) from test2; -- 查询年龄总和 select sum(age) from test2;
5.2 count(*) vs count(字段) 的区别
| 写法 | 含义 |
|---|---|
count(*) | 统计总条数,与字段无关,包含 null 值的行 |
count(字段) | 统计该字段不为空的记录条数 |
示例对比:
select count(*) from testz; -- 返回表中总行数 select count(age) from testz; -- 返回 age 不为空的行数
生产环境建议:统计总行数时使用 count(*),它是统计总行数的标准写法,mysql 会自动选择最优的索引进行优化。
5.3 聚合函数的注意事项
- 聚合函数忽略
null值(count(*)除外) - 聚合函数不能直接用在
where子句中 - 需要对聚合结果进行筛选时,必须使用
having
六、分组查询(group by + having)
分组查询是 sql 中非常重要的功能,用于对数据进行分组统计。
6.1 基础分组
-- 按年龄分组,统计每个年龄的人数 select name, age, count(*) as cnt from test2 group by age;
6.2 group by + having 组合
-- 筛选出人数大于 1 的年龄组 select name, age, count(*) as cnt from test2 group by age having cnt > 1;
6.3 分组查询的执行顺序
from → where → group by → having → select → order by → limit
执行顺序详细解析:
| 步骤 | 子句 | 作用 |
|---|---|---|
| 1 | from | 确定数据来源的表 |
| 2 | where | 在分组前过滤行(不能使用聚合函数) |
| 3 | group by | 对过滤后的数据进行分组 |
| 4 | having | 对分组后的结果进行筛选(可以使用聚合函数) |
| 5 | select | 确定最终查询的字段 |
| 6 | order by | 对结果集排序 |
| 7 | limit | 限制返回的行数 |
6.4 where vs having 的区别
| 对比项 | where | having |
|---|---|---|
| 作用阶段 | 分组前过滤 | 分组后筛选 |
| 能否使用聚合函数 | ❌ 不能 | ✅ 能 |
| 与 group by 的关系 | 可独立使用 | 必须配合 group by 使用 |
实战示例:
-- 查询每个名字的最大年龄,筛选出年龄大于平均值的记录 select name, age, max(age) as maxage from testz group by name; -- 使用 having 对分组结果进行筛选 select name, age, avg(age) as avg from testz group by name having age > avg;
6.5 分组查询的 select 字段原则
select 后面的字段必须满足以下条件之一:
- 出现在
group by子句中 - 被聚合函数包裹
否则,在严格模式下(mysql 默认)会报错。
七、select 语句完整执行流程
将所有子句串联起来,一个完整的 select 语句执行顺序如下:
select distinct 字段列表 from 表名 where 条件表达式 group by 分组字段 having 分组条件 order by 排序字段 limit 偏移量, 行数;
逻辑执行顺序:
1. from 表名 → 确定数据来源 2. where 条件表达式 → 过滤行记录 3. group by 分组字段 → 分组 4. having 分组条件 → 对分组筛选 5. select 字段列表 → 选择字段 6. distinct 去重 → 去重 7. order by 排序 → 排序 8. limit 限制行数 → 分页/截取
八、常见练习题实战
题目一:综合查询
-- 查询年龄在 24~25 之间、且名字包含"张"的记录,按年龄降序排列 select * from testz where age between 24 and 25 and name like '%张%' order by age desc;
题目二:统计分析
-- 统计各年龄段的人数,只显示人数大于 1 的年龄组 select age, count(*) as count from testz group by age having count > 1;
题目三:空值处理
-- 查询没有填写邮箱的用户信息 select name, age, email from testz where email is null; -- 查询有邮箱但年龄未填写的记录 select * from testz where email is not null and age is null;
题目四:数据更新
-- 将所有年龄为 null 的用户年龄更新为 18 update testz set age = 18 where age is null;
九、最佳实践与注意事项
9.1 查询优化建议
- 避免
select *:明确指定所需字段,减少数据传输 - 使用
limit:避免查询过多数据,防止内存溢出 - 合理使用索引:where、order by、join 涉及的字段应建立索引
- 使用
in替代多个or:in的性能更优且更简洁
9.2 数据安全建议
- update/delete 必须带 where:防止误操作全表数据
- 重要操作前备份:drop、truncate 等不可逆操作前务必备份
- 使用事务保护:关键业务操作使用事务,确保数据一致性
- 避免在生产环境使用
truncate:除非非常确定,否则优先使用delete
9.3 代码规范建议
- 关键字大写:
select、from、where等关键字大写,增强可读性 - 合理换行:每个子句单独一行,便于阅读和调试
- 使用别名:复杂查询中使用
as为字段和表起有意义的别名 - 添加注释:复杂的 sql 语句应添加注释说明其业务含义
十、知识点速查表
sql 命令分类速查
| 分类 | 核心命令 | 使用场景 |
|---|---|---|
| ddl | create, alter, drop | 建表、改表结构、删表 |
| dml | insert, update, delete | 增数据、改数据、删数据 |
| dql | select | 查询数据 |
查询子句速查(按执行顺序)
from → where → group by → having → select → distinct → order by → limit
常用函数速查
| 函数 | 含义 | 示例 |
|---|---|---|
count(*) | 统计总行数 | select count(*) from t |
count(col) | 统计 col 非空行数 | select count(age) from t |
avg(col) | 平均值 | select avg(age) from t |
max(col) | 最大值 | select max(age) from t |
min(col) | 最小值 | select min(age) from t |
sum(col) | 求和 | select sum(age) from t |
distinct | 去重 | select distinct name from t |
like '%x%' | 模糊匹配 | where name like '%张%' |
between a and b | 范围查询 | where age between 20 and 30 |
in (v1, v2) | 多值匹配 | where name in ('张三','王五') |
is null | 判空 | where age is null |
结语
mysql 的核心知识体系建立在 ddl + dml + dql 三大支柱之上。掌握建表、改表、删表(ddl),增删改数据(dml),以及灵活运用各种查询方式(dql),是成为一名合格开发者的必备基础。
到此这篇关于从零开始学 mysql sql:ddl、dml、dql 一本通的文章就介绍到这了,更多相关mysql ddl、dml和dql详解内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论