本文介绍如何使用 SQL 语句在 TDSQL Boundless 数据库中更新数据,包括单表更新、多表更新、条件更新、使用
INSERT...ON DUPLICATE KEY UPDATE 实现存在则更新的操作,以及批量更新的最佳实践。前提条件
在执行数据更新操作之前,请确认已满足以下条件:
已创建 TDSQL Boundless 实例并完成连接。请参见连接数据库。
已创建目标数据库和表,且表中已存在需要更新的数据。
当前用户拥有目标表的
UPDATE 权限。使用 UPDATE 更新数据
UPDATE 语句用于修改表中已有记录的列值。以下介绍 UPDATE 语句的基本用法和常见场景。基本语法
UPDATE table_nameSET column1 = new_value1, column2 = new_value2, ...WHERE condition;
参数说明
参数 | 说明 |
table_name | 需要更新的目标表名 |
SET 子句 | 指定需要更新的列及其新值,多列之间使用英文逗号分隔 |
WHERE 子句 | 指定更新条件,只有满足条件的行才会被更新 |
注意:
如果省略
WHERE 子句,UPDATE 语句将更新表中的所有行。在生产环境中执行 UPDATE 操作时,请务必指定 WHERE 条件,以避免误更新全表数据。更新单列值
以下示例将员工编号为1的员工薪资更新为20000。
UPDATE employees SET salary = 20000.00 WHERE id = 1;
执行成功后,返回结果如下:
Query OK, 1 row affected (0.01 sec)Rows matched: 1 Changed: 1 Warnings: 0
同时更新多列值
一条
UPDATE 语句可以同时更新多个列。UPDATE employeesSET salary = 22000.00, department = '架构部'WHERE id = 1;
使用表达式更新
SET 子句中可以使用表达式来计算新值。例如,将所有技术部员工的薪资上调10%。UPDATE employeesSET salary = salary * 1.10WHERE department = '技术部';
使用 UPDATE...ORDER BY...LIMIT 限定更新
UPDATE 语句支持 ORDER BY 和 LIMIT 子句,可以限制更新的行数和顺序。该语法常用于分批更新或只更新前几行的场景。语法格式
UPDATE table_nameSET column1 = new_value1WHERE conditionORDER BY sort_columnLIMIT row_count;
示例
以下示例将薪资最低的3名员工的薪资调整为12000。
UPDATE employeesSET salary = 12000.00ORDER BY salary ASCLIMIT 3;
说明:
使用
ORDER BY 配合 LIMIT 可以确保更新操作的确定性。在需要分批更新大量数据时,建议使用 ORDER BY 主键配合 LIMIT 进行分批处理。多表更新
TDSQL Boundless 支持在一条
UPDATE 语句中同时更新多个表的数据,通常配合 JOIN 子句使用。基本语法
UPDATE table1JOIN table2 ON table1.column = table2.columnSET table1.column1 = new_value1, table2.column2 = new_value2WHERE condition;
示例
以下示例根据部门表中的调薪比例,更新员工表中对应部门员工的薪资。
-- 创建部门调薪表CREATE TABLE department_raise (department VARCHAR(50) PRIMARY KEY,raise_rate DECIMAL(4, 2));INSERT INTO department_raise VALUES ('技术部', 1.15), ('产品部', 1.10), ('市场部', 1.08);-- 使用多表 JOIN 更新员工薪资UPDATE employees eJOIN department_raise d ON e.department = d.departmentSET e.salary = e.salary * d.raise_rate;
使用 INSERT...ON DUPLICATE KEY UPDATE
INSERT...ON DUPLICATE KEY UPDATE 语句在插入数据时,如果遇到主键或唯一键冲突,则执行 UPDATE 操作。该语法适用于"不存在则插入,存在则更新"的业务场景。基本语法
INSERT INTO table_name (column1, column2, ..., columnN)VALUES (value1, value2, ..., valueN)ON DUPLICATE KEY UPDATE column1 = new_value1, column2 = new_value2, ...;
示例
以下示例实现用户评分的插入或更新逻辑:如果用户未对某本书评分,则插入新记录;如果已有评分,则更新评分和评分时间。
-- 创建评分表CREATE TABLE book_ratings (user_id INT,book_id INT,rating TINYINT,rated_at DATETIME,PRIMARY KEY (user_id, book_id));-- 插入或更新评分INSERT INTO book_ratings (user_id, book_id, rating, rated_at)VALUES (1001, 50, 4, NOW())ON DUPLICATE KEY UPDATE rating = VALUES(rating), rated_at = VALUES(rated_at);
注意:
建议仅在包含单个唯一键的表上使用该语法。当表中存在多个唯一键时,可能匹配到非预期的唯一键,导致更新了非目标行。
VALUES() 函数用于引用 INSERT 子句中待插入的值。在 MySQL 8.0.20 及以上版本中,VALUES() 在此场景下已标记为废弃,建议使用别名方式替代。批量更新
当需要更新的数据量很大(例如数万行以上)时,在单个事务中执行大范围的
UPDATE 操作可能导致事务过大、锁持有时间过长等问题。建议将大批量更新拆分为多次小批量更新。批量更新的基本思路
1. 使用
SELECT 查询待更新的记录主键范围。2. 使用
UPDATE...WHERE...LIMIT 分批更新数据。3. 在循环中重复执行步骤2,直到所有数据更新完毕。
示例
以下示例将所有员工的薪资从原始值乘以2,并通过分批更新的方式执行。
1. 添加标记列(可选)
为避免脚本异常中断后重复更新,可以添加一个标记列记录更新状态。
ALTER TABLE employees ADD COLUMN salary_updated TINYINT DEFAULT 0;
2. 分批执行更新
-- 每次更新 1000 行UPDATE employeesSET salary = salary * 2, salary_updated = 1WHERE salary_updated = 0LIMIT 1000;
反复执行上述语句,直到返回的
Rows matched 为0。3. 清理标记列
ALTER TABLE employees DROP COLUMN salary_updated;
说明:
批量更新时,建议每批更新1000 - 10000行数据。每批之间可以适当暂停(例如100ms),以降低对在线业务的影响。
UPDATE 最佳实践
在使用
UPDATE 语句时,建议遵循以下最佳实践。始终使用 WHERE 子句
执行
UPDATE 操作时,必须指定 WHERE 子句来限定更新范围。缺少 WHERE 子句的 UPDATE 语句会更新全表数据,可能导致严重的数据问题。优先使用主键或索引列作为过滤条件
在
WHERE 子句中使用主键或索引列,可以避免全表扫描,提升更新效率。推荐写法
UPDATE employees SET salary = 20000.00 WHERE id = 1;
不推荐写法
UPDATE employees SET salary = 20000.00 WHERE name = '张三';
如果
name 列没有索引,该语句将执行全表扫描。避免在更新中修改主键或唯一键
修改主键或唯一键可能触发额外的索引维护操作,影响性能。如果确实需要修改主键值,建议先删除旧记录,再插入新记录。
大批量更新使用分批方式
当更新数据量超过数万行时,建议使用分批更新策略。单个大事务可能导致以下问题:
锁等待超时(
tdsql_lock_wait_timeout)。事务日志过大,影响数据库性能。
长时间持有行锁,阻塞其他业务操作。
更新前先验证影响范围
在执行
UPDATE 之前,建议先使用相同条件的 SELECT 语句查询将要更新的数据,确认更新范围符合预期。-- 先查看即将被更新的数据SELECT id, name, salary FROM employees WHERE department = '技术部';-- 确认无误后再执行更新UPDATE employees SET salary = salary * 1.10 WHERE department = '技术部';
注意事项
在使用
UPDATE 语句时,请注意以下事项:UPDATE 语句在默认的 autocommit = 1 模式下会自动提交。如果需要回滚,请在执行 UPDATE 前开启事务。当表上存在触发器时,
UPDATE 操作会触发对应的 BEFORE UPDATE 和 AFTER UPDATE 触发器。UPDATE 操作会对匹配的行加行级锁。在高并发场景下,如果多个事务同时更新相同的行,可能产生锁等待或死锁。如果
UPDATE 的 SET 值与当前值相同,受影响的行数 (Changed) 为0,但匹配的行数 (Rows matched) 仍会计入。在分布式事务场景下,跨分片的
UPDATE 操作会使用两阶段提交(Two-Phase Commit,2PC)协议来保证数据一致性。