数据库技术指南(二):MySQL CURD 与高级查询实战
上一篇我们讲解了数据库基础、SQL 语言和 MySQL 核心特性,本文将聚焦CURD 操作(增删改查)和高级查询,带你掌握从 “数据操作” 到 “数据分析” 的全流程技能,是数据库实战的核心内容。
一、C(Create):数据插入(INSERT)
INSERT用于向表中创建(插入)新记录,支持单条、多条记录插入,以及从其他表导入数据。
1. 插入单条记录(全字段)
-- 向student表插入一条学生记录
INSERT INTO student (id, name, age, sex, class_id)
VALUES (1, '张三', 15, '男', 1);
2. 插入单条记录(部分字段)
若字段有默认值或允许NULL,可省略插入:
-- 省略age(假设age允许NULL或有默认值)
INSERT INTO student (id, name, sex, class_id)
VALUES (2, '李四', '女', 1);
3. 插入多条记录
在VALUES后追加多组值,实现批量插入:
INSERT INTO student (id, name, age, sex, class_id)
VALUES (3, '王五', 14, '男', 2),(4, '赵六', 16, '女', 2),(5, '孙七', 15, '男', 3);
4. 从其他表导入数据(INSERT ... SELECT)
将查询结果直接插入目标表:
-- 从temp_student表导入数据到student表
INSERT INTO student (id, name, age, sex, class_id)
SELECT id, name, age, sex, class_id
FROM temp_student
WHERE age > 14;
二、R(Read):数据查询(SELECT)
SELECT是读取数据的核心语法,支持从简单查询到多表关联、聚合统计的全场景需求。
1. 基础查询
(1)查询所有列
SELECT * FROM student; -- 生产环境谨慎使用*,建议明确字段
(2)查询指定列
SELECT name, age FROM student;
2. 条件查询(WHERE)
通过WHERE筛选满足条件的记录:
-- 查询班级为1的学生
SELECT * FROM student WHERE class_id = 1;-- 查询15岁以上的男生
SELECT * FROM student WHERE age > 15 AND sex = '男';
3. 逻辑与比较运算符
| 运算符 | 含义 | 示例 |
|---|---|---|
AND | 逻辑与(同时满足) | age > 15 AND sex = '男' |
OR | 逻辑或(满足其一) | age < 12 OR sex = '女' |
NOT | 逻辑非(取反) | NOT sex = '男' |
= | 等于 | class_id = 1 |
<> / != | 不等于 | age != 15 |
>/</>=/<= | 比较大小 | age >= 18 |
4. 范围与枚举查询
(1)BETWEEN ... AND(范围)
-- 查询13~16岁的学生
SELECT * FROM student WHERE age BETWEEN 13 AND 16;
(2)IN(枚举)
-- 查询id为2、5、6的学生
SELECT * FROM student WHERE id IN (2, 5, 6);
5. 模糊查询(LIKE)
通过通配符%(任意字符)和_(单个字符)实现模糊匹配:
-- 名字含“张”的学生
SELECT * FROM student WHERE name LIKE '%张%';-- 名字以“李”开头且长度为3的学生
SELECT * FROM student WHERE name LIKE '李__';
6. NULL 值判断
-- 查询未设置班级的学生(class_id为NULL)
SELECT * FROM student WHERE class_id IS NULL;
7. 排序(ORDER BY)
-- 按年龄降序排序
SELECT * FROM student ORDER BY age DESC;-- 先按班级升序,再按年龄降序
SELECT * FROM student ORDER BY class_id ASC, age DESC;
8. 分页(LIMIT)
-- 从第6条开始,取5条记录(第2页,每页5条)
SELECT * FROM student LIMIT 5, 5;
9. 聚合函数
用于对一列数据进行统计计算:
-- 统计学生总数
SELECT COUNT(*) AS total FROM student;-- 统计平均年龄
SELECT AVG(age) AS avg_age FROM student;-- 统计最大/最小年龄
SELECT MAX(age) AS max_age, MIN(age) AS min_age FROM student;
10. 分组查询(GROUP BY + HAVING)
-- 按班级分组,统计每班人数和平均年龄
SELECT class_id, COUNT(*) AS num, AVG(age) AS avg_age
FROM student
GROUP BY class_id
HAVING num > 2; -- 只保留人数大于2的班级
11. 多表连接查询
通过JOIN关联多个表的数据:
-- 内连接:仅返回学生和班级都匹配的记录
SELECT s.name, s.age, c.name AS class_name
FROM student s
JOIN class c ON s.class_id = c.id;-- 左连接:返回所有学生,班级无匹配则为NULL
SELECT s.name, s.age, c.name AS class_name
FROM student s
LEFT JOIN class c ON s.class_id = c.id;
三、U(Update):数据更新(UPDATE)
UPDATE用于修改表中已有记录,需结合WHERE避免全表更新。
1. 单表更新(单字段)
-- 将id为1的学生年龄改为16
UPDATE student
SET age = 16
WHERE id = 1;
2. 单表更新(多字段)
-- 同时修改姓名和班级
UPDATE student
SET name = '张三_新', class_id = 2
WHERE id = 1;
3. 多表关联更新
结合JOIN实现多表联动更新:
-- 给“一年级”班级的学生年龄加1
UPDATE student s
JOIN class c ON s.class_id = c.id
SET s.age = s.age + 1
WHERE c.name = '一年级';
4. 基于子查询的更新
-- 将年龄小于平均年龄的学生班级改为3
UPDATE student
SET class_id = 3
WHERE age < (SELECT AVG(age) FROM student);
四、D(Delete):数据删除(DELETE)
DELETE用于删除表中记录,需结合WHERE避免误删全表数据。
1. 删除单条记录
-- 删除id为5的学生
DELETE FROM student
WHERE id = 5;
2. 删除多条记录
-- 删除班级为3且年龄小于15的学生
DELETE FROM student
WHERE class_id = 3 AND age < 15;
3. 多表关联删除
-- 删除“一年级”班级的所有学生(需先关闭外键检查或确保级联删除)
DELETE s
FROM student s
JOIN class c ON s.class_id = c.id
WHERE c.name = '一年级';
4. 清空表(TRUNCATE)
TRUNCATE是快速清空表数据的方式(效率高于DELETE,但不记录日志,且自增主键会重置):
TRUNCATE TABLE student;
五、高级查询:从数据操作到数据分析
1. 子查询(嵌套查询)
将一个查询的结果作为另一个查询的条件或数据源:
-- 找出年龄大于平均年龄的学生
SELECT *
FROM student
WHERE age > (SELECT AVG(age) FROM student);
2. 窗口函数(MySQL 8.0 + 支持)
用于 “分组不聚合”,在保留原始行的同时进行组内统计(如排名、累计和):
-- 计算每个学生的年龄排名
SELECT name, age, RANK() OVER (ORDER BY age DESC) AS age_rank
FROM student;
3. 公共表表达式(CTE,MySQL 8.0 + 支持)
将复杂查询拆分为 “临时表”,提升可读性:
WITH class_avg_age AS (SELECT class_id, AVG(age) AS avg_age FROM student GROUP BY class_id
)
SELECT s.name, s.age, c.avg_age
FROM student s
JOIN class_avg_age c ON s.class_id = c.class_id;
六、CURD 操作的最佳实践
1. 数据安全
- 避免裸写 UPDATE/DELETE:必须加
WHERE条件,否则会修改 / 删除全表数据。 - 备份重要数据:执行高危操作(如
TRUNCATE、批量UPDATE)前,先备份数据。
2. 性能优化
- INSERT 批量操作:尽量使用多条
VALUES或LOAD DATA INFILE实现批量插入,减少网络交互。 - UPDATE/DELETE 加索引:
WHERE条件字段需建立索引,避免全表扫描。 - SELECT 按需查询:避免使用
SELECT *,明确指定需要的字段,减少 IO 开销。
3. 事务控制
对于跨操作的原子性需求(如转账 “扣钱 + 进账”),需用事务包裹 CURD 操作:
START TRANSACTION;-- 步骤1:扣钱
UPDATE account SET balance = balance - 100 WHERE user_id = 1;-- 步骤2:进账
UPDATE account SET balance = balance + 100 WHERE user_id = 2;COMMIT; -- 提交事务(全部成功)
-- ROLLBACK; -- 回滚事务(任意步骤失败则执行)
七、实战综合案例
需求:统计每个班级的男生、女生人数,找出人数最多的班级,并更新该班级所有学生的年龄 + 1,最后删除年龄小于 12 的学生。
-- 1. 分组统计班级男女人数
SELECT class_id,SUM(IF(sex = '男', 1, 0)) AS male_num,SUM(IF(sex = '女', 1, 0)) AS female_num,COUNT(*) AS total_num
FROM student
GROUP BY class_id;-- 2. 找出人数最多的班级ID
SELECT class_id
FROM student
GROUP BY class_id
ORDER BY COUNT(*) DESC
LIMIT 1
INTO @max_class_id;-- 3. 更新该班级学生年龄+1
UPDATE student
SET age = age + 1
WHERE class_id = @max_class_id;-- 4. 删除年龄小于12的学生
DELETE FROM student
WHERE age < 12;
八、总结
本文系统讲解了 MySQL 的 CURD 操作和高级查询技巧,从 “数据创建” 到 “数据分析”,覆盖了所有业务场景的需求。掌握这些技能,你能在数据库实战中既保证操作的正确性,又兼顾性能与安全。
结合上一篇的 “数据库基础与 MySQL 核心特性”,你已构建起完整的数据库知识体系。后续可深入学习 “数据库索引优化”“事务与锁机制” 等进阶内容,进一步提升数据库管理能力。
