MySQL数据更新 #

一、UPDATE语句概述 #

1.1 基本语法 #

sql
UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;

1.2 示例表结构 #

sql
CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50),
    age INT,
    email VARCHAR(100),
    status TINYINT DEFAULT 1,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

INSERT INTO users (name, age, email, status) VALUES
    ('John', 25, 'john@example.com', 1),
    ('Jane', 30, 'jane@example.com', 1),
    ('Bob', 28, 'bob@example.com', 0);

二、基本更新 #

2.1 更新单个字段 #

sql
UPDATE users 
SET age = 26 
WHERE id = 1;

2.2 更新多个字段 #

sql
UPDATE users 
SET 
    name = 'John Smith',
    age = 27,
    email = 'john.smith@example.com'
WHERE id = 1;

2.3 更新所有行 #

sql
-- 危险操作!更新所有行
UPDATE users SET status = 1;

-- 建议先查询确认
SELECT COUNT(*) FROM users WHERE status != 1;

三、条件更新 #

3.1 使用WHERE条件 #

sql
-- 根据ID更新
UPDATE users SET status = 0 WHERE id = 1;

-- 根据名称更新
UPDATE users SET age = 31 WHERE name = 'Jane';

-- 多条件更新
UPDATE users 
SET status = 1 
WHERE age > 25 AND status = 0;

-- 使用IN条件
UPDATE users 
SET status = 0 
WHERE id IN (1, 2, 3);

-- 使用BETWEEN条件
UPDATE users 
SET status = 1 
WHERE age BETWEEN 20 AND 30;

3.2 使用子查询 #

sql
-- 更新满足子查询条件的记录
UPDATE users 
SET status = 0 
WHERE id IN (
    SELECT user_id FROM orders 
    WHERE total_amount > 10000
);

-- 使用EXISTS
UPDATE users u
SET status = 1
WHERE EXISTS (
    SELECT 1 FROM orders o 
    WHERE o.user_id = u.id AND o.status = 'completed'
);

四、表达式更新 #

4.1 数值计算 #

sql
-- 年龄加1
UPDATE users SET age = age + 1 WHERE id = 1;

-- 年龄减1
UPDATE users SET age = age - 1 WHERE id = 1;

-- 价格打折
UPDATE products SET price = price * 0.9 WHERE category = 'electronics';

4.2 字符串操作 #

sql
-- 字符串拼接
UPDATE users SET name = CONCAT(name, ' Jr') WHERE age < 20;

-- 字符串替换
UPDATE users 
SET email = REPLACE(email, 'old.com', 'new.com');

-- 大小写转换
UPDATE users SET name = UPPER(name) WHERE id = 1;
UPDATE users SET name = LOWER(name) WHERE id = 2;

4.3 日期操作 #

sql
-- 更新为当前时间
UPDATE users SET updated_at = NOW() WHERE id = 1;

-- 日期加减
UPDATE subscriptions 
SET expire_date = DATE_ADD(expire_date, INTERVAL 30 DAY)
WHERE user_id = 1;

-- 设置为当前日期
UPDATE users SET last_login = CURDATE() WHERE id = 1;

五、多表更新 #

5.1 UPDATE JOIN语法 #

sql
-- 根据关联表更新
UPDATE users u
JOIN orders o ON u.id = o.user_id
SET u.status = 1
WHERE o.total_amount > 1000;

-- LEFT JOIN更新
UPDATE users u
LEFT JOIN profiles p ON u.id = p.user_id
SET u.status = 0
WHERE p.id IS NULL;

5.2 多表关联更新 #

sql
UPDATE orders o
JOIN users u ON o.user_id = u.id
JOIN products p ON o.product_id = p.id
SET o.status = 'completed'
WHERE u.status = 1 AND p.stock > 0;

六、ORDER BY和LIMIT #

6.1 限制更新数量 #

sql
-- 只更新前10条
UPDATE users 
SET status = 0 
WHERE status = 1 
LIMIT 10;

6.2 按顺序更新 #

sql
-- 按创建时间更新最早的10条
UPDATE users 
SET status = 1 
WHERE status = 0 
ORDER BY created_at ASC 
LIMIT 10;

七、特殊更新 #

7.1 条件表达式更新 #

sql
-- 使用CASE WHEN
UPDATE users 
SET status = CASE
    WHEN age < 18 THEN 0
    WHEN age >= 18 AND age < 60 THEN 1
    ELSE 2
END;

-- 使用IF函数
UPDATE users 
SET status = IF(age >= 18, 1, 0);

7.2 NULL值处理 #

sql
-- 更新NULL值
UPDATE users SET age = 0 WHERE age IS NULL;

-- 使用IFNULL
UPDATE users 
SET name = IFNULL(name, 'Unknown');

-- 使用COALESCE
UPDATE users 
SET email = COALESCE(email, 'no-email@example.com');

7.3 JSON字段更新 #

sql
-- 更新JSON字段
UPDATE users 
SET profile = JSON_SET(profile, '$.age', 25)
WHERE id = 1;

-- 更新JSON数组
UPDATE users 
SET tags = JSON_ARRAY_APPEND(tags, '$', 'new_tag')
WHERE id = 1;

-- 删除JSON字段
UPDATE users 
SET profile = JSON_REMOVE(profile, '$.temp_field')
WHERE id = 1;

八、安全更新 #

8.1 开启安全模式 #

sql
-- 查看安全模式状态
SHOW VARIABLES LIKE 'sql_safe_updates';

-- 开启安全模式
SET sql_safe_updates = 1;

-- 关闭安全模式
SET sql_safe_updates = 0;

8.2 安全模式限制 #

sql
-- 安全模式下,必须使用键列作为条件
-- 错误示例:
UPDATE users SET status = 0;
-- ERROR 1175 (HY000): You are using safe update mode

-- 正确示例:
UPDATE users SET status = 0 WHERE id = 1;

8.3 更新前检查 #

sql
-- 更新前先查询
SELECT * FROM users WHERE status = 0;

-- 确认数量
SELECT COUNT(*) FROM users WHERE status = 0;

-- 使用事务
START TRANSACTION;
UPDATE users SET status = 1 WHERE status = 0;
-- 确认结果
SELECT * FROM users WHERE status = 0;
-- 确认无误后提交
COMMIT;
-- 如有问题回滚
ROLLBACK;

九、更新性能优化 #

9.1 使用索引 #

sql
-- 确保WHERE条件使用索引
-- 查看执行计划
EXPLAIN UPDATE users SET status = 1 WHERE email = 'john@example.com';

-- 如果email有索引,更新更快

9.2 分批更新 #

sql
-- 大批量更新分批进行
-- 每次更新1000条
UPDATE users 
SET status = 1 
WHERE status = 0 
LIMIT 1000;

-- 循环执行直到影响行数为0

9.3 避免全表扫描 #

sql
-- 不推荐:无索引条件的更新
UPDATE users SET status = 1 WHERE name LIKE '%John%';

-- 推荐:使用索引条件
UPDATE users SET status = 1 WHERE id IN (
    SELECT id FROM users WHERE name LIKE '%John%'
);

十、常见错误处理 #

10.1 唯一键冲突 #

sql
-- 错误信息
UPDATE users SET email = 'jane@example.com' WHERE id = 1;
-- ERROR 1062 (23000): Duplicate entry 'jane@example.com' for key 'uk_email'

-- 解决方案:检查唯一值
SELECT id FROM users WHERE email = 'jane@example.com';

10.2 外键约束错误 #

sql
-- 错误信息
UPDATE orders SET user_id = 999 WHERE id = 1;
-- ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails

-- 解决方案:确保外键值存在
SELECT id FROM users WHERE id = 999;

10.3 数据类型错误 #

sql
-- 错误信息
UPDATE users SET age = 'abc' WHERE id = 1;
-- ERROR 1366 (HY000): Incorrect integer value: 'abc' for column 'age'

-- 解决方案:提供正确类型
UPDATE users SET age = 25 WHERE id = 1;

十一、更新返回值 #

11.1 查看影响行数 #

sql
UPDATE users SET status = 1 WHERE id = 1;
-- Query OK, 1 row affected

-- 在应用程序中获取
-- PHP: $affected = $pdo->rowCount();
// Java: int affected = statement.executeUpdate();

11.2 查看警告 #

sql
UPDATE users SET age = 200 WHERE id = 1;
SHOW WARNINGS;

十二、总结 #

更新数据要点:

操作 语法
单字段更新 UPDATE table SET col = val WHERE …
多字段更新 UPDATE table SET col1=val1, col2=val2 WHERE …
表达式更新 UPDATE table SET col = col + 1 WHERE …
多表更新 UPDATE t1 JOIN t2 SET … WHERE …
限制更新 UPDATE table SET … LIMIT n

最佳实践:

  1. 始终使用WHERE条件,避免误更新全表
  2. 更新前先查询确认
  3. 重要操作使用事务
  4. 大批量更新分批进行
  5. 开启安全更新模式

下一步,让我们学习数据删除!

最后更新:2026-03-26