MySQL 增删改查(CRUD)完全指南
本文档专门讲 对表里数据的增、删、改、查,即 CRUD:Create(增)、Read(查)、Update(改)、Delete(删)。每一步都配有详细说明和大量示例,适合零基础新手跟着做。
目录
- 什么是 CRUD
- 操作前准备:库和表
- 增(Create)——INSERT
- 查(Read)——SELECT
- 改(Update)——UPDATE
- 删(Delete)——DELETE
- 增删改查综合示例
- 必须牢记的注意点
- 常见错误与解决
- 命令速查表
1. 什么是 CRUD
CRUD 是四个英文单词的首字母:
| 字母 | 英文 | 含义 | 对应 SQL |
|---|---|---|---|
| C | Create | 增加数据 | INSERT |
| R | Read | 查询数据 | SELECT |
| U | Update | 修改数据 | UPDATE |
| D | Delete | 删除数据 | DELETE |
也就是说:
- 增 = 往表里插入新的一行或多行 → 用 INSERT
- 查 = 从表里读出满足条件的行 → 用 SELECT
- 改 = 把表里某些行的列更新成新值 → 用 UPDATE
- 删 = 把表里某些行删掉 → 用 DELETE
下面会按 增 → 查 → 改 → 删 的顺序,逐个讲语法和示例。
2. 操作前准备:库和表
增删改查都是针对某张表的,表又在某个数据库里,所以要先选库、确保表存在。
2.1 选择数据库
USE school;
2.2 准备一张示例表
后面所有示例都用下面这张表,你可以先建好,跟着一起练:
CREATE TABLE IF NOT EXISTS students (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
gender CHAR(1) DEFAULT '男',
age INT,
class_name VARCHAR(20),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
- id:主键,自增,插入时可以省略。
- name:必填(NOT NULL)。
- gender:有默认值
'男',不写就填'男'。 - age、class_name:可空。
- created_at:不写则自动填当前时间。
3. 增(Create)——INSERT
INSERT 用来往表里插入新行。
3.1 基本语法(指定列名,推荐)
INSERT INTO 表名 (列1, 列2, 列3, ...) VALUES (值1, 值2, 值3, ...);
- 列名 和 值 要一一对应:列1 对应 值1,列2 对应 值2……
- 字符串、日期用单引号,数字不用。
- 没有写出来的列:若没有默认值且允许 NULL,会是 NULL;若有默认值或是自增,按默认/自增处理。
示例:插入一条学生记录
INSERT INTO students (name, gender, age, class_name)
VALUES ('张三', '男', 18, '高一1班');
这里没写 id 和 created_at:
id自增,会自动变成 1;created_at有默认值,会自动填当前时间。
再插几条:
INSERT INTO students (name, gender, age, class_name) VALUES ('李四', '女', 17, '高一2班');
INSERT INTO students (name, gender, age, class_name) VALUES ('王五', '男', 18, '高一1班');
INSERT INTO students (name, gender, age, class_name) VALUES ('赵六', '女', 17, '高一2班');
INSERT INTO students (name, gender, age, class_name) VALUES ('钱七', '男', 19, '高一1班');
3.2 一次插入多行(推荐,效率更高)
用一条 INSERT 写多组 VALUES,用逗号隔开:
INSERT INTO students (name, gender, age, class_name) VALUES
('张三', '男', 18, '高一1班'),
('李四', '女', 17, '高一2班'),
('王五', '男', 18, '高一1班'),
('赵六', '女', 17, '高一2班'),
('钱七', '男', 19, '高一1班');
效果和上面分 5 条插入一样,但只执行一次,速度更快。
3.3 插入时写全所有列(不推荐)
如果按表定义的顺序把每一列都写上,可以省略列名,直接 VALUES:
INSERT INTO students VALUES (NULL, '孙八', '男', 18, '高一1班', NOW());
- id 写 NULL 时,自增列会自动生成新 id。
- 缺点:列顺序一变或表结构一改就容易错,可读性差,建议始终写上列名。
3.4 利用默认值:少写几列
有默认值的列可以不写,数据库会自动填默认值:
-- gender 有默认值 '男',不写就是 '男'
INSERT INTO students (name, age, class_name) VALUES ('周九', 18, '高一1班');
-- created_at 有 DEFAULT CURRENT_TIMESTAMP,不写就是当前时间
-- 上面所有示例都没写 created_at,都是自动填的
3.5 主动插入 NULL(可空列)
若列允许 NULL,可以显式插入 NULL:
INSERT INTO students (name, gender, age, class_name) VALUES ('吴十', '女', NULL, NULL);
表示“年龄、班级未知”。
3.6 INSERT IGNORE(主键/唯一冲突时跳过)
若表里有主键或唯一索引,插入时若和已有行冲突会报错。
用 INSERT IGNORE 时,遇到冲突就跳过该行,不报错:
INSERT IGNORE INTO students (id, name, gender, age, class_name) VALUES
(1, '重复id', '男', 18, '高一1班');
-- 若 id=1 已存在,这条会被忽略,不会报错
3.7 REPLACE INTO(主键/唯一冲突时替换,了解即可)
REPLACE INTO 的写法与 INSERT 类似,但若主键或唯一键冲突,会先删掉旧行,再插入新行(相当于“替换”):
REPLACE INTO students (id, name, gender, age, class_name) VALUES
(1, '新张三', '男', 19, '高一2班');
一般用 INSERT 或 INSERT … ON DUPLICATE KEY UPDATE 更常见,REPLACE 了解即可。
3.8 增(INSERT)小结
- 推荐写法:INSERT INTO 表名 (列1, 列2, …) VALUES (值1, 值2, …);
- 多行:多组 VALUES 用逗号隔开。
- 字符串、日期用单引号;数字不用;可空列可写 NULL。
- 有默认值或自增的列可以不写。
4. 查(Read)——SELECT
SELECT 用来从表里读出数据,是使用频率最高的语句。
4.1 基本语法
SELECT 列1, 列2, ... FROM 表名 [WHERE 条件] [ORDER BY 排序列] [LIMIT 条数];
- SELECT 列:要查哪些列;FROM 表名:从哪张表查。
- WHERE:筛选行(可选)。
- ORDER BY:排序(可选)。
- LIMIT:只取前几条(可选)。
下面先讲最基础的“查哪些列”“查哪些行”,WHERE/ORDER BY/LIMIT 的详细用法可以配合你已有的「条件与排序」文档一起看。
4.2 查询所有列:SELECT *
*星号 ``** 表示“所有列”:
SELECT * FROM students;
会返回表里所有行、所有列。适合调试,正式代码里建议尽量写具体列名,方便维护。
示例输出(示意):
+----+------+--------+------+------------+---------------------+
| id | name | gender | age | class_name | created_at |
+----+------+--------+------+------------+---------------------+
| 1 | 张三 | 男 | 18 | 高一1班 | 2025-02-26 10:00:00 |
| 2 | 李四 | 女 | 17 | 高一2班 | 2025-02-26 10:00:00 |
...
+----+------+--------+------+------------+---------------------+
4.3 查询指定列
只查需要的列,列名用逗号隔开:
SELECT name, age, class_name FROM students;
示例:只查姓名和班级
SELECT name, class_name FROM students;
4.4 给列起别名(AS)
用 AS 可以把列在结果里显示成另一个名字(不影响表结构):
SELECT name AS 姓名, age AS 年龄, class_name AS 班级 FROM students;
AS 可以省略,用空格隔开“列”和“别名”也行(不推荐,可读性差):
SELECT name 姓名, age 年龄 FROM students;
4.5 去重:DISTINCT
若多行在“选中列”上完全相同,只保留一行,用 DISTINCT:
SELECT DISTINCT class_name FROM students;
结果里每个班级只出现一次。
4.6 带条件查询:WHERE(重要)
WHERE 用来筛选行,只返回满足条件的记录。
示例:查高一1班的学生
SELECT * FROM students WHERE class_name = '高一1班';
示例:查年龄大于等于 18 的
SELECT * FROM students WHERE age >= 18;
示例:查年龄 18 且在高一1班
SELECT * FROM students WHERE age = 18 AND class_name = '高一1班';
示例:查姓名为张三或李四
SELECT * FROM students WHERE name = '张三' OR name = '李四';
示例:查年龄在 17 到 18 之间(含 17 和 18)
SELECT * FROM students WHERE age BETWEEN 17 AND 18;
示例:查学号在 1、2、3 里的
SELECT * FROM students WHERE id IN (1, 2, 3);
示例:查姓名包含“三”的(模糊匹配)
SELECT * FROM students WHERE name LIKE '%三%';
- % 表示任意多个字符;_ 表示一个字符。
'%三%':中间有“三”即可;'张%':以“张”开头。
示例:查年龄为 NULL 的(空值判断)
SELECT * FROM students WHERE age IS NULL;
注意:不能用 age = NULL,必须用 IS NULL 或 IS NOT NULL。
4.7 排序:ORDER BY
ORDER BY 指定按哪一列(或几列)排序,ASC 升序,DESC 降序,不写默认 ASC。
示例:按年龄升序
SELECT * FROM students ORDER BY age ASC;
示例:按年龄降序,年龄相同按 id 升序
SELECT * FROM students ORDER BY age DESC, id ASC;
4.8 限制条数:LIMIT
只取前几条,用 LIMIT:
SELECT * FROM students ORDER BY id LIMIT 3;
分页常用:跳过前 N 条,再取 M 条,用 LIMIT N, M(注意:第一个数是“跳过”,第二个是“取几条”):
-- 跳过前 2 条,取接下来 3 条(即第 3、4、5 条)
SELECT * FROM students ORDER BY id LIMIT 2, 3;
4.9 查(SELECT)小结
- 查所有列:*SELECT FROM 表名;查指定列:SELECT 列1, 列2 FROM 表名**。
- 别名:SELECT 列 AS 别名。
- 去重:SELECT DISTINCT 列 FROM 表名。
- 条件:WHERE 条件;排序:ORDER BY 列 ASC/DESC;条数:LIMIT n 或 LIMIT 跳过, 条数。
5. 改(Update)——UPDATE
UPDATE 用来修改表里已有行的列值。
5.1 基本语法
UPDATE 表名 SET 列1=新值1, 列2=新值2, ... [WHERE 条件];
- SET:要改的列和对应的新值,多列用逗号隔开。
- WHERE:只对满足条件的行更新;不写 WHERE 会更新整张表,非常危险!
5.2 修改某一行的某一列
示例:把 id 为 1 的学生的年龄改成 19
UPDATE students SET age = 19 WHERE id = 1;
示例:把姓名为“李四”的学生的班级改成“高一1班”
UPDATE students SET class_name = '高一1班' WHERE name = '李四';
5.3 修改多列
示例:把 id 为 2 的学生的年龄改为 18,班级改为“高一1班”
UPDATE students SET age = 18, class_name = '高一1班' WHERE id = 2;
5.4 按条件修改多行
示例:把所有“高一2班”的学生的年龄都改成 17
UPDATE students SET age = 17 WHERE class_name = '高一2班';
示例:把所有年龄为 NULL 的填成 18
UPDATE students SET age = 18 WHERE age IS NULL;
5.5 用表达式更新(了解)
SET 右边可以是表达式,例如“年龄加 1”:
UPDATE students SET age = age + 1 WHERE id = 1;
5.6 危险写法:不加 WHERE(务必避免)
UPDATE students SET age = 18;
这会把表中所有行的 age 都改成 18!
改(UPDATE)前一定要确认 WHERE 条件是否正确,最好先 SELECT 查一遍再 UPDATE。
5.7 改(UPDATE)小结
- 语法:UPDATE 表名 SET 列=值 [, 列2=值2 …] WHERE 条件。
- 必须养成习惯:先想清楚要改哪几行,写上 WHERE,必要时先用 SELECT 验证。
6. 删(Delete)——DELETE
DELETE 用来删除表里的行(记录),不删表结构。
6.1 基本语法
DELETE FROM 表名 [WHERE 条件];
- WHERE:只删除满足条件的行;不写 WHERE 会删除表中所有数据,极其危险!
6.2 删除指定的一行
示例:删除 id 为 5 的学生
DELETE FROM students WHERE id = 5;
6.3 按条件删除多行
示例:删除所有高一2班的学生
DELETE FROM students WHERE class_name = '高一2班';
示例:删除年龄小于 18 的
DELETE FROM students WHERE age < 18;
6.4 危险写法:不加 WHERE(务必避免)
DELETE FROM students;
会删除 students 表里的所有行,表还在,但数据全没了,且无法恢复。
删(DELETE)前必须确认 WHERE,建议先用 SELECT … WHERE 同一条件看一遍再删。
6.5 清空整张表:TRUNCATE(了解)
若确定要清空整张表,可以用 TRUNCATE:
TRUNCATE TABLE students;
- 效果:表里数据全部清空,自增 id 会从 1 重新开始。
- 与 DELETE FROM students; 的区别:TRUNCATE 不能加 WHERE,且通常更快;DELETE 可以带 WHERE 只删部分行。
- 新手阶段用 DELETE + WHERE 即可,清空全表时再考虑 TRUNCATE。
6.6 删(DELETE)小结
- 语法:DELETE FROM 表名 WHERE 条件。
- 绝不建议在没写 WHERE 的情况下执行 DELETE。
7. 增删改查综合示例
下面用同一张表,按顺序做一遍增、查、改、删,方便你整段练习。
USE school;
-- 确保表存在
CREATE TABLE IF NOT EXISTS students (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
gender CHAR(1) DEFAULT '男',
age INT,
class_name VARCHAR(20),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- ========== 增 ==========
INSERT INTO students (name, gender, age, class_name) VALUES
('张三', '男', 18, '高一1班'),
('李四', '女', 17, '高一2班'),
('王五', '男', 18, '高一1班');
-- ========== 查 ==========
SELECT * FROM students;
SELECT name, age FROM students WHERE class_name = '高一1班';
SELECT * FROM students ORDER BY age DESC LIMIT 2;
-- ========== 改 ==========
UPDATE students SET age = 19 WHERE name = '张三';
SELECT * FROM students WHERE name = '张三'; -- 确认改对了
UPDATE students SET class_name = '高一1班' WHERE name = '李四';
-- ========== 删 ==========
-- 先查再删,避免删错
SELECT * FROM students WHERE name = '王五';
DELETE FROM students WHERE name = '王五';
SELECT * FROM students;
8. 必须牢记的注意点
8.1 UPDATE 和 DELETE 一定要带 WHERE
- UPDATE 表 SET … 不加 WHERE → 更新全表。
- DELETE FROM 表 不加 WHERE → 删除全表数据。
- 习惯:先 SELECT … WHERE 条件 看会影响哪些行,再写 UPDATE/DELETE … WHERE 同一条件。
8.2 字符串和日期用单引号
- 正确:
'张三'、'高一1班'、'2025-02-26'。 - 错误:
张三(会被当成列名等)、数字不需要引号。
8.3 NULL 的判断
- 判断是否为空:WHERE 列 IS NULL 或 WHERE 列 IS NOT NULL。
- 不能写 列 = NULL(结果永远为假)。
8.4 主键、唯一列插入时不要冲突
- 主键或唯一列重复插入会报错,可用 INSERT IGNORE 或 ON DUPLICATE KEY UPDATE 处理(见前文)。
9. 常见错误与解决
9.1 报错:Column count doesn’t match value count
原因:INSERT 时列的数量和值的数量不一致。
解决:检查 INSERT INTO 表 (列1, 列2, …) VALUES (值1, 值2, …),列和值个数、顺序一致。
9.2 报错:Data too long for column ‘xxx’
原因:插入的字符串超过该列定义的长度(如 VARCHAR(10) 却插了 20 个字符)。
解决:缩短内容,或用 ALTER TABLE 把该列长度改大。
9.3 报错:Incorrect date value
原因:日期格式不对或超出范围。
解决:日期写成 ‘YYYY-MM-DD’,如 '2025-02-26';日期时间写成 ‘YYYY-MM-DD HH:MM:SS’。
9.4 把整张表都更新/删除了
原因:UPDATE 或 DELETE 忘了写 WHERE,或 WHERE 条件写错(如永远为真)。
解决:只能从备份恢复;以后务必先 SELECT … WHERE 条件 确认再执行 UPDATE/DELETE。
10. 命令速查表
| 操作 | 基本语法 |
|---|---|
| 增(单行) | INSERT INTO 表 (列1,列2) VALUES (值1,值2); |
| 增(多行) | INSERT INTO 表 (列1,列2) VALUES (v1,v2),(v1,v2); |
| 查(全部) | SELECT * FROM 表; |
| 查(指定列) | SELECT 列1,列2 FROM 表; |
| 查(带条件) | SELECT * FROM 表 WHERE 条件; |
| 查(排序) | SELECT * FROM 表 ORDER BY 列 ASC/DESC; |
| 查(条数) | SELECT * FROM 表 LIMIT n; 或 LIMIT 跳过,n |
| 改 | UPDATE 表 SET 列=值 [,列2=值2] WHERE 条件; |
| 删 | DELETE FROM 表 WHERE 条件; |
提醒:UPDATE 和 DELETE 务必写对 WHERE,必要时先用 SELECT 验证条件。
按本文把增、查、改、删各练几遍,再结合「条件与排序」文档把 WHERE、ORDER BY、LIMIT 用熟,就能覆盖日常大部分对单表的 CRUD 操作了。建议在本地建好 students 表,把第 7 节整段跑一遍,再自己设计几条 INSERT/SELECT/UPDATE/DELETE 练手。