源本科技 | 码上会

MySQL DML 数据操作语言

2026/03/14
30
0

什么是 DML

DML(Data Manipulation Language,数据操作语言)是 SQL 中用于操作数据库表中具体数据的核心部分。如果说 DDL 是建造大楼的框架,那么 DML 就是在大楼里搬运家具、装修房间和清理垃圾的过程。

核心作用

  • 增 (Insert):向表中添加新的数据行。

  • 改 (Update):修改表中已存在的数据行。

  • 删 (Delete):从表中移除特定的数据行。

  • 查 (Select):虽然 SELECT 常被单独归类为 DQL,但在广义的数据操作中,它也是获取数据的关键步骤。

关键特性

  • 事务性:DML 操作通常包含在事务中。这意味着你可以执行一系列插入、更新或删除操作,然后选择提交 (COMMIT) 使更改永久生效,或者回滚 (ROLLBACK) 撤销所有更改。

  • 安全性:尤其是 UPDATEDELETE 操作,如果忘记加 WHERE 子句,可能会导致全表数据被修改或清空,这是生产环境中极其严重的事故。


插入数据

INSERT 语句用于向数据库表中添加新记录。

基础语法

-- 指定列名插入(推荐方式)
INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);

最佳实践:始终显式列出列名。

  • 原因:如果表结构发生变化(如增加了新列),不写列名的语句可能会报错或插入错误的数据。显式列名让代码更具可读性和健壮性。

批量插入

为了提高性能,可以在一条语句中插入多行数据,减少网络交互和解析开销。

INSERT INTO table_name (column1, column2, column3, ...)
VALUES 
    (value1_a, value2_a, value3_a),
    (value1_b, value2_b, value3_b),
    (value1_c, value2_c, value3_c);

实战案例

假设我们有一个 employees 表:

-- 插入单条记录
INSERT INTO employees (employee_id, first_name, last_name, salary)
VALUES (101, 'John', 'Doe', 50000);

-- 插入多条记录(高效写法)
INSERT INTO employees (employee_id, first_name, last_name, salary)
VALUES
    (102, 'Jane', 'Smith', 60000),
    (103, 'Bob', 'Johnson', 55000),
    (104, 'Alice', 'Williams', 58000);

特殊场景处理

  • 自增主键:如果主键是 AUTO_INCREMENT,插入时可以忽略该列,数据库会自动生成。

    INSERT INTO users (username, email) VALUES ('tom', 'tom@example.com');
  • 默认值:如果某列定义了 DEFAULT 值且插入时未指定,将自动填入默认值。

  • 部分列插入:只插入非空且有值的列,其他列设为 NULL 或默认值。


更新数据

UPDATE 语句用于修改表中已存在的记录。务必谨慎使用!

基础语法

UPDATE table_name 
SET column1 = value1, column2 = value2, ... 
WHERE condition;
  • SET 子句:指定要修改的列和新值。可以修改单列,也可以同时修改多列(用逗号分隔)。

  • WHERE 子句至关重要。它指定哪些行需要被更新。

    • 有 WHERE:只更新符合条件的行。

    • 无 WHERE更新表中的所有行!这通常是灾难性的。

实战案例

-- 场景 1:修改单个字段
-- 将产品 ID 为 101 的价格调整为 25.99
UPDATE products 
SET price = 25.99 
WHERE product_id = 101;

-- 场景 2:基于现有值计算更新
-- 给销售部门 (Sales) 的所有员工加薪 10%
UPDATE employees 
SET salary = salary * 1.1 
WHERE department = 'Sales';

-- 场景 3:同时修改多个字段
-- 更新用户信息并记录最后修改时间
UPDATE users 
SET email = 'new_email@example.com', last_login = NOW() 
WHERE user_id = 5;

安全提示:在执行 UPDATE 之前,建议先执行对应的 SELECT 语句,确认 WHERE 条件选中的行正是你想要修改的行。

-- 先检查
SELECT * FROM employees WHERE department = 'Sales';
-- 确认无误后再执行 UPDATE

删除数据

DELETE 语句用于从表中移除记录。

基础语法

DELETE FROM table_name 
WHERE condition;
  • WHERE 子句:同样至关重要。

    • 有 WHERE:删除符合条件的行。

    • 无 WHERE清空整张表的所有数据(但表结构保留)。

DELETE vs TRUNCATE

虽然 DELETE FROM table_name (不带 WHERE) 和 TRUNCATE TABLE table_name 都能清空表,但它们有本质区别:

特性

DELETE (不带 WHERE)

TRUNCATE

类型

DML (可回滚)

DDL (通常不可回滚)

速度

较慢 (逐行删除,记录日志)

极快 (直接释放数据页)

自增重置

不重置 自增计数器

重置 自增计数器归零

触发器

会触发 DELETE 触发器

通常不触发触发器

条件删除

支持 WHERE 条件

不支持,只能全删

实战案例

-- 场景 1:删除特定记录
-- 删除员工 ID 为 103 的记录
DELETE FROM employees 
WHERE employee_id = 103;

-- 场景 2:批量删除
-- 删除所有已离职 (status='left') 的员工
DELETE FROM employees 
WHERE status = 'left';

警告:生产环境中严禁随意执行不带 WHEREDELETE 语句。如果需要清空表且不需要保留自增 ID,优先使用 TRUNCATE


综合演练

基于之前创建的 users 表,完成以下数据操作流程。

环境准备

假设 users 表结构如下:

CREATE TABLE users (
    user_id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(255) UNIQUE NOT NULL,
    password VARCHAR(255) NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    registration_date DATETIME DEFAULT CURRENT_TIMESTAMP
);

任务 1:插入数据

需求:插入两个新用户。

  • 用户 1:john_doe, 密码 password123, 邮箱 john@example.com

  • 用户 2:jane_doe, 密码 pass456, 邮箱 jane@example.com

  • 注册日期使用默认当前时间。

INSERT INTO users (username, password, email)
VALUES 
    ('john_doe', 'password123', 'john@example.com'),
    ('jane_doe', 'pass456', 'jane@example.com');

注:registration_date 未指定,将自动填入当前时间。

任务 2:更新数据

需求:发现 john_doe 的密码泄露,需要将其更新为 new_password789

UPDATE users 
SET password = 'new_password789' 
WHERE username = 'john_doe';

安全检查:先 SELECT * FROM users WHERE username = 'john_doe'; 确认只有一行受影响。

任务 3:删除数据

需求:用户 jane_doe 申请注销账号,需要从数据库中移除。

DELETE FROM users 
WHERE username = 'jane_doe';

任务 4:验证结果

执行查询以确认操作结果:

SELECT * FROM users;

预期结果

  • 表中只剩下 john_doe 的记录。

  • john_doe 的密码已变为 new_password789

  • jane_doe 的记录已消失。