MySQL 表操作核心指南:CRUD 与进阶技巧
目录
1. Create:插入数据
1.1 基础插入语法
实战案例:学生表数据插入
1.2 冲突处理:插入否则更新
语法与案例
1.3 替换插入:冲突则删除后新增
案例
2. Retrieve:查询数据
2.1 基础查询语法
2.2 常见查询场景实战
场景 1:指定列与表达式查询
场景 2:去重查询(DISTINCT)
场景 3:条件过滤(WHERE)
场景 4:结果排序(ORDER BY)
场景 5:分页查询(LIMIT)
2.3 NULL 值处理
3. Update:更新数据
3.1 基础语法
3.2 实战案例
4. Delete:删除数据
4.1 基础删除(DELETE)
4.2 截断表(TRUNCATE)
5. 进阶操作:插入查询结果与聚合函数
5.1 插入查询结果(INSERT ... SELECT)
5.2 聚合函数
实战案例
5.3 分组查询(GROUP BY)
案例:按部门统计工资
MySQL 中表的操作围绕 CRUD 展开,即创建(Create)、读取(Retrieve)、更新(Update)、删除(Delete)。掌握这些基础操作是数据库使用的核心,本文将结合实战案例,详细拆解每个操作的语法、场景及注意事项。
1. Create:插入数据
插入数据是向表中添加记录的基础操作,需根据场景选择 “单行 / 多行”“全列 / 指定列” 插入,同时处理主键 / 唯一键冲突问题。
1.1 基础插入语法
INSERT [INTO] 表名 [(列1, 列2, ...)]
VALUES (值1, 值2, ...) [, (值1, 值2, ...)];
- 若不指定列,
VALUES
的顺序和数量必须与表定义完全一致。 - 支持一次性插入多行数据,用逗号分隔多个值列表。
实战案例:学生表数据插入
- 先创建学生表(含自增主键
id
、唯一学号sn
)
CREATE TABLE student(id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, sn INT NOT NULL UNIQUE COMMENT '学号', name VARCHAR(20) NOT NULL, qq VARCHAR(15) UNIQUE COMMENT 'QQ号'
);
- 单行全列插入(需包含所有列,
id
自增可传NULL
或省略)
-- 手动指定id=1,其他列按顺序传值
INSERT INTO student VALUES(1, 123, '张三', '123456');
-- 省略id,依赖自增(需指定列名)
INSERT INTO student (sn, name, qq) VALUES(124, '李四', '156954');
- 多行指定列插入(高效批量添加)
INSERT INTO student (sn, name, qq)
VALUES(125, '王五', '523124'), (126, '赵六', '529124');
1.2 冲突处理:插入否则更新
当插入数据触发主键或唯一键冲突时,可通过ON DUPLICATE KEY UPDATE
自动更新冲突行,避免报错。
语法与案例
INSERT INTO 表名 VALUES(...)
ON DUPLICATE KEY UPDATE 列1=新值1, 列2=新值2;
-- 场景1:主键id=1已存在,更新sn和name
INSERT INTO student VALUES(1, 127, '孙权', '456543')
ON DUPLICATE KEY UPDATE sn=127, name='孙权';
-- 执行结果:2 rows affected(1行冲突,1行更新)-- 场景2:无冲突,直接插入
INSERT INTO student VALUES(5, 128, '刘备', '165463')
ON DUPLICATE KEY UPDATE sn=128, name='刘备';
-- 执行结果:1 row affected(新数据插入)-- 场景3:冲突但更新后值与原值一致
INSERT INTO student VALUES(5, 128, '刘备', '165463')
ON DUPLICATE KEY UPDATE sn=128, name='刘备';
-- 执行结果:0 rows affected(无实际更新)
1.3 替换插入:冲突则删除后新增
若冲突时需 “删除原冲突行 + 插入新行”,可用REPLACE
,但需注意会丢失原行的非指定列数据。
案例
-- 主键id=6已存在,先删除原行再插入新行
REPLACE INTO student VALUES(6, 129, '张飞', '544562');
-- 执行结果:2 rows affected(1行删除,1行插入)
2. Retrieve:查询数据
查询是最常用的操作,通过SELECT
语法实现 “筛选列、过滤行、排序、分页”,核心是按需提取数据。
2.1 基础查询语法
SELECT [DISTINCT] {* | 列1 [AS 别名1], 列2 [AS 别名2], ...}
FROM 表名
[WHERE 条件]
[ORDER BY 列 [ASC/DESC], ...]
[LIMIT 偏移量, 条数];
2.2 常见查询场景实战
先创建考试成绩表exam_result
并插入测试数据:
CREATE TABLE exam_result ( id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20) NOT NULL, chinese FLOAT DEFAULT 0.0, math FLOAT DEFAULT 0.0, english FLOAT DEFAULT 0.0
);INSERT INTO exam_result (name, chinese, math, english)
VALUES
('唐三藏', 67, 98, 56), ('孙悟空', 87, 78, 77),
('猪悟能', 88, 98, 90), ('曹孟德', 82, 84, 67),
('刘玄德', 55, 85, 45), ('孙权', 70, 73, 78),
('宋公明', 75, 65, 30);
场景 1:指定列与表达式查询
- 查询指定列:按需选择列,可调整顺序
-- 按“姓名→语文→数学”顺序查询 SELECT name, chinese, math FROM exam_result;
- 表达式查询:计算衍生字段(如总分)
-- 计算语文+数学总分,给列起别名“语文数学总分” SELECT name, chinese + math AS 语文数学总分 FROM exam_result;
场景 2:去重查询(DISTINCT)
当结果有重复值时,用DISTINCT
去重(作用于所有查询列的组合):
-- 去重查询数学成绩(原数据中98分重复)
SELECT DISTINCT math FROM exam_result;
场景 3:条件过滤(WHERE)
通过比较运算符(>
, <
, BETWEEN
, IN
)和逻辑运算符(AND
, OR
, NOT
)筛选行:
-- 1. 英语不及格(<60)的同学
SELECT name, english FROM exam_result WHERE english < 60;-- 2. 语文成绩在80-90之间(含边界)
SELECT name, chinese FROM exam_result WHERE chinese BETWEEN 80 AND 90;-- 3. 数学成绩是58、59、98、99中的一个
SELECT name, math FROM exam_result WHERE math IN (58, 59, 98, 99);-- 4. 姓“孙”的同学(模糊匹配,%表示任意字符)
SELECT name FROM exam_result WHERE name LIKE '孙%';
场景 4:结果排序(ORDER BY)
- 默认为升序(
ASC
),降序需显式指定(DESC
)。 - 支持多列排序,优先级按列的顺序排列。
-- 按数学降序,数学相同则按英语升序
SELECT name, math, english FROM exam_result
ORDER BY math DESC, english ASC;
场景 5:分页查询(LIMIT)
用于批量获取数据,避免一次性加载过多记录,语法:
LIMIT 条数
:从第 0 条开始,取指定条数。LIMIT 偏移量, 条数
:从 “偏移量” 开始,取指定条数(偏移量从 0 开始)。
-- 分页:每页3条,查第2页(偏移量=3,即跳过前3条)
SELECT id, name, chinese FROM exam_result
ORDER BY id LIMIT 3, 3;
2.3 NULL 值处理
NULL
表示 “未知值”,不能用=
比较,需用IS NULL
或IS NOT NULL
:
-- 查询QQ号不为空的学生
SELECT name, qq FROM student WHERE qq IS NOT NULL;-- 比较NULL:=返回NULL,<=>(NULL安全比较)返回1(相等)或0(不相等)
SELECT NULL <=> NULL; -- 结果:1
SELECT NULL = NULL; -- 结果:NULL
3. Update:更新数据
更新操作用于修改表中已有记录,需谨慎使用WHERE
条件,避免误更新全表数据。
3.1 基础语法
UPDATE 表名
SET 列1=新值1, 列2=新值2, ...
[WHERE 条件]
[ORDER BY 列 [ASC/DESC]]
[LIMIT 条数];
3.2 实战案例
-- 场景1:更新单条记录(孙悟空数学成绩改为80)
UPDATE exam_result
SET math = 80
WHERE name = '孙悟空';-- 场景2:更新多条记录(总成绩倒数3名的数学成绩+30)
UPDATE exam_result
SET math = math + 30
ORDER BY chinese + math + english
LIMIT 3;-- 场景3:更新全表(所有同学语文成绩翻倍,慎用!)
UPDATE exam_result
SET chinese = chinese * 2;
4. Delete:删除数据
删除操作分为 “删除部分记录” 和 “清空表”,需注意数据不可恢复,操作前建议备份。
4.1 基础删除(DELETE)
删除指定条件的记录,支持WHERE
、ORDER BY
和LIMIT
:
-- 场景1:删除单条记录(删除孙悟空的成绩)
DELETE FROM exam_result
WHERE name = '孙悟空';-- 场景2:删除全表记录(保留表结构,自增ID不重置)
DELETE FROM for_delete; -- for_delete为测试表
注意:DELETE
删除全表后,自增 ID 会继续从上次的最大值递增(如上次 ID=3,删除后新增 ID=4)。
4.2 截断表(TRUNCATE)
清空表中所有记录,且重置自增 ID(恢复为 1),执行速度比DELETE
快,但不可回滚(无法恢复数据):
-- 截断表:清空数据+重置自增ID
TRUNCATE TABLE for_truncate;-- 插入新数据:ID从1开始
INSERT INTO for_truncate (name) VALUES('D'); -- ID=1
5. 进阶操作:插入查询结果与聚合函数
5.1 插入查询结果(INSERT ... SELECT)
将一个查询的结果直接插入到另一个表中,常用于数据迁移或去重:
-- 场景:删除student表中的重复记录(保留1条)
1. 创建与原表结构相同的空表
CREATE TABLE student_no_dup LIKE student;2. 将原表去重后的数据插入新表
INSERT INTO student_no_dup
SELECT DISTINCT * FROM student;3. 替换原表(备份原表→新表改名)
RENAME TABLE student TO student_old;
RENAME TABLE student_no_dup TO student;
5.2 聚合函数
聚合函数用于对数据进行统计计算,常见函数如下:
函数 | 作用 |
---|---|
COUNT ([DISTINCT] 列) | 统计记录数(DISTINCT 去重) |
SUM ([DISTINCT] 列) | 计算列的总和(仅数字列有效) |
AVG ([DISTINCT] 列) | 计算列的平均值(仅数字列有效) |
MAX (列) | 取列的最大值 |
MIN (列) | 取列的最小值 |
实战案例
-- 1. 统计学生总数(COUNT(*)包含NULL,COUNT(qq)不包含NULL)
SELECT COUNT(*) AS 学生总数 AS QQ已填数量 FROM student;-- 2. 统计数学成绩的总分、平均分、最高分
SELECT SUM(math) AS 数学总分, AVG(math) AS 数学平均分, MAX(math) AS 数学最高分
FROM exam_result;-- 3. 统计数学成绩>70的最低分
SELECT MIN(math) AS 数学最低分(>70) FROM exam_result WHERE math > 70;
5.3 分组查询(GROUP BY)
结合GROUP BY
对数据按指定列分组,再用聚合函数统计每组数据,用HAVING
过滤分组结果(类似WHERE
但作用于分组)。
案例:按部门统计工资
假设有员工表emp
(含deptno
部门号、sal
工资):
-- 1. 按部门分组,统计每个部门的平均工资和最高工资
SELECT deptno AS 部门号, AVG(sal) AS 平均工资, MAX(sal) AS 最高工资
FROM emp
GROUP BY deptno;-- 2. 筛选平均工资<2000的部门(HAVING过滤分组结果)
SELECT deptno AS 部门号, AVG(sal) AS 平均工资
FROM emp
GROUP BY deptno
HAVING 平均工资 < 2000;
执行顺序:FROM
→ WHERE
(过滤行)→ GROUP BY
(分组)→ HAVING
(过滤分组)→ SELECT
(查询列)→ ORDER BY
(排序)→ LIMIT
(分页)。