在 MySQL 中,INSERT ON DUPLICATE KEY UPDATE 是一种非常实用的语句,用于在插入数据时,如果遇到唯一键或主键冲突,就执行更新操作,而不是报错。这个功能特别适合处理“存在则更新,不存在则插入”的场景。
基本语法
该语句的基本结构如下:
INSERT INTO table_name (column1, column2, ...) VALUES (value1, value2, ...) ON DUPLICATE KEY UPDATE column1 = VALUES(column1), column2 = VALUES(column2), ...;说明:
当插入的数据导致唯一索引或主键冲突时,MySQL 会执行 UPDATE 部分。 如果没有冲突,则正常插入新记录。 VALUES(column) 表示你尝试插入的值,不是当前表中的值。使用场景示例
假设有一个用户登录统计表:
CREATE TABLE user_stats ( user_id INT PRIMARY KEY, login_count INT DEFAULT 0, last_login DATETIME );我们希望每次用户登录时:
如果 user_id 不存在,就插入一条新记录,login_count 为 1。 如果已存在,就将 login_count 加 1,并更新最后登录时间。可以这样写:
INSERT INTO user_stats (user_id, login_count, last_login) VALUES (1001, 1, NOW()) ON DUPLICATE KEY UPDATE login_count = login_count + 1, last_login = NOW();第一次执行:插入 user_id=1001 的记录。
第二次执行:发现主键冲突,于是更新 login_count 和 last_login。
注意事项与技巧
必须有唯一索引(UNIQUE)或主键(PRIMARY KEY),否则不会触发“duplicate key”错误,也就不会执行 UPDATE。 UPDATE 中可以引用 VALUES() 函数获取插入时的值,比如 VALUES(login_count) 返回的是你试图插入的那个值。 可以只更新部分字段,不需要更新所有列。 如果 UPDATE 后的值和原值一样,MySQL 可能仍会认为发生了“变更”,影响 affected rows 的返回值(通常变为 2)。实际应用建议
适用于计数器、状态更新、缓存同步等幂等性操作。 比先 SELECT 再 INSERT/UPDATE 更高效,避免了多次查询和潜在的竞争条件。 注意不要滥用,确保业务逻辑确实符合“插入或更新”模式。基本上就这些。只要表上有唯一约束,就可以安全使用 INSERT ON DUPLICATE KEY UPDATE 来简化逻辑。不复杂但容易忽略细节,比如 VALUES() 的用法。
