CRUD 入门:数据的增、查、改、删

在前一篇中,我们成功创建了数据库和表,并初步了解了数据类型。接下来,我们将进入数据库操作中最核心、最常用的部分------CRUD。CRUD 是四个基本操作的缩写:C reate(增加)、R ead(查询)、U pdate(更新)、Delete(删除)。这四项操作几乎是所有数据库应用的基础,熟练掌握它们,就掌握了与数据库交互的"对话能力"。

本文将以之前创建的 users 表为载体,带你系统学习:

  • 使用 INSERT 插入单行、多行数据
  • 使用 SELECT 查询数据(全列、指定列、表达式、别名、去重)
  • 使用 UPDATE 修改数据
  • 使用 DELETE 删除数据
  • 实战:完成用户表的增删改查

1. 插入数据:INSERT INTO

1.1 基本语法

sql 复制代码
INSERT INTO 表名 [(列1, 列2, ...)]
VALUES (值1, 值2, ...),
       (值3, 值4, ...),
       ...;
  • 列名列表是可选的,如果省略,则需要按表定义顺序为所有列提供值(自动增长的列可以指定 NULLDEFAULT)。
  • 可以一次性插入多行数据,以提高效率。

1.2 插入单行

我们以上一篇创建的 users 表为例,插入一条完整的记录:

sql 复制代码
INSERT INTO users (username, email, password, birthdate, status)
VALUES ('alice', 'alice@example.com', 'hashed_pw_alice', '1995-06-15', 1);

因为 id 列是 AUTO_INCREMENT,我们无需手动指定,MySQL 会自动生成。mobileavatar_urlsignaturelast_login_at 等列有默认值或允许 NULL,未指定则会自动使用默认值(NULL 或指定默认值)。

验证插入结果:

sql 复制代码
SELECT * FROM users;

1.3 插入多行

可以一次性插入多条记录,用逗号分隔:

sql 复制代码
INSERT INTO users (username, email, password, birthdate, status)
VALUES
    ('bob', 'bob@example.com', 'hashed_pw_bob', '1990-01-20', 1),
    ('carol', 'carol@example.com', 'hashed_pw_carol', '2000-08-03', 1),
    ('dave', 'dave@example.com', 'hashed_pw_dave', '1985-12-12', 1);

1.4 插入指定列

如果你的 INSERT 语句只包含了部分列,那么其他未指定的列将使用默认值或 NULL(取决于定义)。例如,只插入必填字段:

sql 复制代码
INSERT INTO users (username, email, password)
VALUES ('eve', 'eve@example.com', 'hashed_pw_eve');

此时,birthdate 会为 NULL,status 会使用默认值 1。


2. 查询数据:SELECT

SELECT 是 SQL 中使用最频繁的语句,用于从表中检索数据。

2.1 基本查询

查询所有列

sql 复制代码
SELECT * FROM users;

使用 * 很方便,但在生产环境中通常不推荐,因为它可能带来不必要的 I/O 开销,且无法利用覆盖索引优化。明确列出所需列是更好的习惯。

查询指定列

sql 复制代码
SELECT username, email FROM users;

2.2 表达式与别名

你可以在 SELECT 列表中使用表达式。例如,如果我们想展示一个由 usernameemail 组合而成的"显示名":

sql 复制代码
SELECT username, CONCAT(username, ' <', email, '>') AS display_name
FROM users;
  • AS 用于给列或表达式取别名,方便阅读。别名也可以用在后续的 ORDER BYGROUP BY 中(但需注意标准 SQL 的执行顺序)。
  • 如果别名包含空格或特殊字符,需要用反引号或双引号包裹,如 AS 'display name'

算术运算示例:假设有一张商品表,可以使用 price * quantity 计算总价。

2.3 去重:DISTINCT

如果想查看用户表中有哪些不同的出生年份(假设我们存储的是 DATE 类型),可以使用 DISTINCT

sql 复制代码
SELECT DISTINCT YEAR(birthdate) AS birth_year FROM users WHERE birthdate IS NOT NULL;

DISTINCT 作用在整个选择列表上,即去掉所有选择列都相同的行。

2.4 查询常量与函数

SELECT 也可以查询不来自表的数据,如系统信息:

sql 复制代码
SELECT VERSION(), NOW(), 'Hello' AS greeting;

这在调试或写存储过程时很有用。


3. 修改数据:UPDATE

UPDATE 语句用于修改表中已存在的行。

3.1 基本语法

sql 复制代码
UPDATE 表名
SET 列1 = 新值1, 列2 = 新值2, ...
[WHERE 条件];

⚠️ 强烈建议先写 WHERE 条件再执行,避免误更新整个表!

3.2 示例:更新用户状态和签名

将用户 alice 的状态改为"冻结"(0),并添加个性签名:

sql 复制代码
UPDATE users
SET status = 0, signature = '暂时离开,勿念'
WHERE username = 'alice';

验证更新:

sql 复制代码
SELECT username, status, signature FROM users WHERE username = 'alice';

如果忘记添加 WHERE 条件,所有行的 status 都会被更新,后果将非常严重。

3.3 使用表达式更新

可以在 SET 中使用当前列的值。比如把所有用户的激活状态反转(0 变 1,1 变 0)------ 虽然这不是常规操作,但演示一下:

sql 复制代码
UPDATE users SET status = 1 - status;

这会把 status = 0 的变为 1,status = 1 的变为 0。执行前务必确认 WHERE 条件是否必要。


4. 删除数据:DELETE

4.1 基本语法

sql 复制代码
DELETE FROM 表名
[WHERE 条件];

同样需要万分小心,没有 WHERE 条件的 DELETE 会清空整个表! 如果只是想要清空表,更高效的方式是使用 TRUNCATE TABLE 表名,它会重置自增计数器且不记录逐行删除日志。

4.2 删除指定行

删除用户 bob

sql 复制代码
DELETE FROM users WHERE username = 'bob';

如果存在多条 username = 'bob',则会全部删除。建议 DELETE 时使用唯一键(如主键)来精确定位。

4.3 删除所有行(慎用)

sql 复制代码
DELETE FROM users;

DROP TABLE users; 不同,DELETE 仅删除数据,保留表结构和索引等。如果要清空表且希望重置自增值,可以使用:

sql 复制代码
TRUNCATE TABLE users;

TRUNCATE 是一个 DDL 操作,无法回滚,速度极快。


5. 实战:完成用户表的增删改查

让我们把前面的知识串起来,模拟一个简单的用户管理场景。假设我们有一个初始为空的 users 表(可重新创建或清空数据后操作)。

5.1 插入用户

sql 复制代码
INSERT INTO users (username, email, password, birthdate) VALUES
('zhangsan', 'zhangsan@example.com', 'pass_zhangsan', '1998-07-10'),
('lisi', 'lisi@example.com', 'pass_lisi', '2002-11-25'),
('wangwu', 'wangwu@example.com', 'pass_wangwu', '1995-03-08'),
('zhaoliu', 'zhaoliu@example.com', 'pass_zhaoliu', '1990-09-17');

5.2 查询所有已激活用户

sql 复制代码
SELECT id, username, email, birthdate
FROM users
WHERE status = 1;

5.3 更新用户邮箱

lisi 更换了邮箱:

sql 复制代码
UPDATE users
SET email = 'lisi_new@example.com'
WHERE username = 'lisi';

5.4 删除某个用户

zhaoliu 注销账号:

sql 复制代码
DELETE FROM users WHERE username = 'zhaoliu';

5.5 验证最终结果

sql 复制代码
SELECT * FROM users;

你应该能看到 zhangsanlisiwangwu 三个人,其中 lisi 的邮箱已更新,zhaoliu 已消失。

扩展练习

  1. 尝试批量插入 10 条用户记录,其中有几个用户的状态设为 0。
  2. 编写一个 UPDATE 语句,将所有 2000 年后出生的用户签名统一设置为"千禧一代"。
    (提示:WHERE birthdate > '2000-01-01')
  3. 删除所有状态为 0 的用户(使用 DELETE)。

6. 小结

本文我们学习了 MySQL 中最基础的 CRUD 操作:

  • INSERT 插入数据,支持单行、多行及指定列;
  • SELECT 查询数据,包括指定列、表达式、别名和 DISTINCT
  • UPDATE 修改数据,必须谨慎加 WHERE 条件;
  • DELETE 删除数据,同样需确认条件,清空表时可考虑 TRUNCATE。

这些操作是后续所有复杂查询和数据处理的基础。下一篇我们将深入 SELECT 的过滤与排序,让数据查询更加精准和高效。

思考题

  1. 如果用 INSERT INTO users VALUES (NULL, ...) 插入,会发生什么?(提示:自增列可以显式给 NULL 吗?)
  2. DELETETRUNCATE 的区别是什么?在事务中使用它们,回滚后效果有何不同?
  3. 假设我们误执行了无 WHERE 的 UPDATE,有没有办法恢复?(提示:需要提前准备什么?)

参考资料


相关推荐
2301_808414381 小时前
MySQL中的复合查询和索引
数据库·mysql
我也不曾来过11 小时前
MYSQL的基本查询
数据库·mysql
小江的记录本1 小时前
【MySQL】MySQL日志体系:redo log/undo log/binlog 三者区别、两阶段提交、如何保证数据一致性
java·数据库·后端·python·sql·mysql·面试
BD_Marathon1 小时前
mysql8.0启动报错
mysql
jran-2 小时前
MySQL 视图
数据库·mysql
无小道2 小时前
Mysql——用C语言链接数据库
数据库·mysql
未若君雅裁4 小时前
MySQL-MVCC核心原理-版本链ReadView与可见性判断
数据库·mysql
拾贰_C11 小时前
【Ubuntu | 公共工作站 | mysql 】 MySQL残留物残留数据
linux·mysql·ubuntu
知识汲取者12 小时前
每日一篇高频面试题系列之【MySQL 锁】
数据库·mysql