跳到主要内容

2.3 插入、更新与删除数据

表建好了还是空的,就像刚买的冰箱——接下来该往里放东西了。本节学习 DML(数据操作语言)三兄弟:INSERT(增)、UPDATE(改)、DELETE(删)。我们还会把全书通用的示例数据一次性插入 school 库的四张表,后面所有查询章节都靠这批数据。

📖 本节导读

  • 掌握 INSERT 的三种写法:指定列插入、全列插入、一次插入多行
  • 把示例数据完整插入 class、student、course、score 四张表
  • 掌握 UPDATE ... SET ... WHERE,牢记"先 SELECT 验证再 UPDATE"的保命习惯
  • 掌握 DELETE FROM ... WHERE,以及 DELETETRUNCATE 的区别

开始前先切换到 school 库:

USE school;

一、插入数据:INSERT

1.1 指定列插入(推荐写法)

INSERT INTO 表名 (1,2, ...) VALUES (1,2, ...);

例如往班级表插入"一班":

INSERT INTO class (name) VALUES ('一班');
Query OK, 1 row affected (0.01 sec)

注意几个细节:

  • 我们没有给 id 赋值——因为 id 是 AUTO_INCREMENT 自增列,MySQL 会自动填 1、2、3……
  • 字符串和日期要加单引号'一班''2005-03-15';数字不用引号。
  • 列和值要一一对应:几个列名就给几个值,顺序也要对上。

1.2 全列插入

如果给所有列都提供值(包括 id),可以省略列名:

INSERT INTO class VALUES (2, '二班');

这种写法简短,但不推荐在正式项目里用:一旦表结构变了(比如加了一列),语句就会报错,而且别人读代码时不知道每个值对应哪列。教程里为了演示数据的完整性,下面部分语句会使用它。

1.3 一次插入多行

每行数据一对括号,用逗号隔开,比一条条插快得多:

INSERT INTO 表名 (1,2, ...) VALUES
(1,2, ...),
(1,2, ...),
(1,2, ...);

1.4 正式插入全书示例数据

下面这批数据全书通用,请原样完整执行(如果之前做实验插过数据,可先执行 TRUNCATE TABLE 表名; 清空后再插,TRUNCATE 见本节第四部分):

-- ① 班级表:2 个班
INSERT INTO class (id, name) VALUES
(1, '一班'),
(2, '二班');

-- ② 学生表:5 名学生
INSERT INTO student (id, name, gender, birthday, class_id) VALUES
(1, '张三', '男', '2005-03-15', 1),
(2, '李四', '男', '2005-07-01', 1),
(3, '王小红', '女', '2006-01-20', 2),
(4, '赵敏', '女', '2005-11-08', 2),
(5, '陈刚', '男', '2006-05-30', 1);

-- ③ 课程表:3 门课
INSERT INTO course (id, name, teacher) VALUES
(1, '数学', '王老师'),
(2, '英语', '李老师'),
(3, '计算机', '张老师');

-- ④ 成绩表:12 条成绩(注意最后一条成绩为 NULL)
INSERT INTO score (id, student_id, course_id, score) VALUES
(1, 1, 1, 90.0),
(2, 1, 2, 85.0),
(3, 1, 3, 88.0),
(4, 2, 1, 76.0),
(5, 2, 2, 92.0),
(6, 3, 1, 95.0),
(7, 3, 2, 60.0),
(8, 3, 3, 70.0),
(9, 4, 1, 58.0),
(10, 4, 3, 81.0),
(11, 5, 2, 73.0),
(12, 5, 3, NULL);

几点说明:

  • 这里显式写了 id,是为了保证全书数据完全一致(自增列也允许手动指定值)。
  • NULL 表示"空、未知"——学号 5 的陈刚选了计算机课但还没出成绩,所以成绩是 NULL。注意 NULL 不加引号,加了引号就变成字符串 'NULL' 了。
  • 赵敏(id=4)没有英语成绩、陈刚(id=5)没有数学成绩——这些"缺口"是故意留的,后面讲连接查询时会用到。

插入完成后验证一下(SELECT * 表示查询表中全部数据,下一节详细讲):

SELECT * FROM student;
+----+--------+--------+------------+----------+
| id | name | gender | birthday | class_id |
+----+--------+--------+------------+----------+
| 1 | 张三 | 男 | 2005-03-15 | 1 |
| 2 | 李四 | 男 | 2005-07-01 | 1 |
| 3 | 王小红 | 女 | 2006-01-20 | 2 |
| 4 | 赵敏 | 女 | 2005-11-08 | 2 |
| 5 | 陈刚 | 男 | 2006-05-30 | 1 |
+----+--------+--------+------------+----------+
5 rows in set (0.00 sec)

1.5 体验默认值 DEFAULT

student 表的 gender 列有 DEFAULT '男'。插入时不给 gender,MySQL 会自动填 '男':

INSERT INTO student (name, birthday, class_id) VALUES ('测试生', '2006-01-01', 1);
SELECT * FROM student WHERE name = '测试生';
+----+--------+--------+------------+----------+
| id | name | gender | birthday | class_id |
+----+--------+--------+------------+----------+
| 6 | 测试生 | 男 | 2006-01-01 | 1 |
+----+--------+--------+------------+----------+
1 row in set (0.00 sec)

id 自动变成了 6,gender 自动填了 '男'。这条测试数据不属于标准示例数据,我们在下面学 DELETE 时正好把它删掉。

二、更新数据:UPDATE

2.1 语法

UPDATE 表名 SET1 = 新值1,2 = 新值2 WHERE 条件;

WHERE 用来指定改哪些行。例如:假设录入时发现陈刚的英语成绩录错了,应该是 75 分(这里只是演示,改完我们会改回 73 保持示例数据一致):

UPDATE score SET score = 75.0 WHERE id = 11;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0

Rows matched: 1 表示条件匹配了 1 行,Changed: 1 表示实际修改了 1 行。

2.2 忘写 WHERE 的灾难后果

⚠️ 如果不写 WHERE,UPDATE 会修改表中的每一行!

-- 千万别执行这条!它会把 12 条成绩全部改成 100 分
UPDATE score SET score = 100;

在真实工作中,一条忘写 WHERE 的 UPDATE 可能瞬间把几百万用户的余额改成同一个数——这是数据库事故排行榜上的常客。而且执行后没有"撤销"按钮。

2.3 保命好习惯:先用 SELECT 验证 WHERE 条件

在执行 UPDATE / DELETE 之前,先把 WHERE 条件放到 SELECT 里跑一遍,确认查出来的正是你想改的那些行:

-- 第 1 步:先查,确认命中的就是想改的那一行
SELECT * FROM score WHERE id = 11;
+----+------------+-----------+-------+
| id | student_id | course_id | score |
+----+------------+-----------+-------+
| 11 | 5 | 2 | 75.0 |
+----+------------+-----------+-------+
1 row in set (0.00 sec)

确认无误后,再把 SELECT * 换成 UPDATE ... SET。现在把成绩改回 73.0,保持和全书示例数据一致:

-- 第 2 步:确认后再改
UPDATE score SET score = 73.0 WHERE id = 11;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

一次也可以更新多列,用逗号隔开:

UPDATE student SET gender = '女', class_id = 2 WHERE name = '测试生';

(这条也是演示,"测试生"马上就要被删除了,改不改无所谓。)

三、删除数据:DELETE

3.1 语法

DELETE FROM 表名 WHERE 条件;

按照保命流程,先 SELECT 确认,再删掉刚才的测试数据:

SELECT * FROM student WHERE name = '测试生'; -- 确认只有这 1 行
DELETE FROM student WHERE name = '测试生';
Query OK, 1 row affected (0.01 sec)

再查一遍,student 表恢复为标准的 5 名学生。

⚠️ 和 UPDATE 一样:DELETE 不写 WHERE 会删光整张表的数据! DELETE FROM student;(无 WHERE)执行完,5 名学生全没了。

小提示:删掉 id=6 的测试生后,自增计数器仍停留在 6,下次插入会从 7 开始。如果想让编号严格连续,可以用下面的 TRUNCATE 重置(但会清空全表),新手知道这个现象即可,不必强求 id 连续。

3.2 DELETE 与 TRUNCATE 的区别

TRUNCATE TABLE 表名; 也能清空一张表,但它和 DELETE FROM 表名;(不带 WHERE)有本质区别:

对比项DELETE FROM 表名TRUNCATE TABLE 表名
所属分类DML(一行一行删数据)DDL(相当于把表拆了按原结构重建)
能否带 WHERE 只删部分✅ 能❌ 不能,只能整表清空
自增计数器不重置(继续从原来的最大值往后编号)重置为 1
速度数据量大时较慢极快
能否回滚(在事务中撤销)✅ 可以❌ 不可以

类比:DELETE 像把笔记本上的字一行一行用橡皮擦掉(擦哪几行可以挑,擦错了还可能救回来);TRUNCATE 像直接换一本同款新笔记本(快,但什么都不剩,页码也从 1 重新开始)。

经验:要删部分数据用 DELETE ... WHERE;确定要整表清空重来(比如重灌测试数据)用 TRUNCATE

⚠️ 新手常见坑

  1. UPDATE / DELETE 忘写 WHERE:全表遭殃且无法撤销。养成"先 SELECT 验证,再改/删"的肌肉记忆。
  2. NULL 写成了 'NULL':加引号就变成 4 个字符的字符串了。真正的空值是不带引号的 NULL
  3. 字符串和日期忘加单引号VALUES (张三) 会报错,要写 VALUES ('张三');日期同理 '2005-03-15'
  4. 列数和值的个数对不上:报 Column count doesn't match value count。检查括号里列和值是否一一对应。
  5. 给自增主键重复的值:报 Duplicate entry '1' for key 'PRIMARY',主键不能重复。
  6. 用 TRUNCATE 只想删几行:TRUNCATE 没有 WHERE,一执行整表清空,别拿它当 DELETE 用。

📝 小结

  • INSERT INTO 表 (列...) VALUES (值...):指定列插入(推荐);省略列名则必须给全所有列的值;多行插入用逗号连接多组括号。
  • 自增列可不填由 MySQL 自动编号;有 DEFAULT 的列不填则用默认值;空值写 NULL 不加引号。
  • UPDATE 表 SET 列=值 WHERE 条件DELETE FROM 表 WHERE 条件WHERE 是安全带,先 SELECT 验证再动手
  • DELETE 可挑行删、可回滚、不重置自增;TRUNCATE 整表清空、极快、重置自增、不可回滚。
  • 本节已插入全书标准示例数据:2 个班级、5 名学生、3 门课程、12 条成绩(其中 1 条为 NULL)。

✍️ 练习题

1. 往 course 表插入一门课程:名称'物理',教师'刘老师'(id 让 MySQL 自动生成)。写出语句,并预测新行的 id 是多少。

参考答案
INSERT INTO course (name, teacher) VALUES ('物理', '刘老师');

course 表已有 id 1、2、3,自增列会分配 id = 4。(练习完记得 DELETE FROM course WHERE id = 4; 保持示例数据一致。)

2. 用一条 INSERT 语句往 class 表插入'三班'和'四班'两行。

参考答案
INSERT INTO class (name) VALUES ('三班'), ('四班');

(练习完可用 DELETE FROM class WHERE name IN ('三班', '四班'); 删掉。)

3. 把 score 表中 id 为 9 的成绩从 58.0 改为 59.0。要求写出"保命流程"的完整两步,最后再写出改回 58.0 的语句。

参考答案
-- 第 1 步:先验证 WHERE 条件
SELECT * FROM score WHERE id = 9;
-- 第 2 步:确认后更新
UPDATE score SET score = 59.0 WHERE id = 9;
-- 改回,保持示例数据一致
UPDATE score SET score = 58.0 WHERE id = 9;

4. 判断题:DELETE FROM score;TRUNCATE TABLE score; 效果完全一样。

参考答案

错。两者都会清空数据,但 DELETE 是逐行删除、不重置自增计数器、在事务中可回滚;TRUNCATE 相当于重建表、自增重置为 1、不可回滚且速度更快。

5. 小明执行了 UPDATE student SET class_id = 2; 想把王小红调到二班,结果发生了什么?正确的语句应该怎么写?

参考答案

他忘了写 WHERE,导致全部 5 名学生的 class_id 都被改成了 2。正确写法:

UPDATE student SET class_id = 2 WHERE name = '王小红';

(王小红本来就在二班,这也提醒我们改之前先 SELECT * FROM student WHERE name = '王小红'; 看一眼。)