如何避免INSERT ... ON DUPLICATE KEY UPDATE导致自增ID持续增长?
问题分析与解决方案
你遇到的核心问题是INSERT...ON DUPLICATE KEY UPDATE没有触发更新逻辑,反而每次都执行插入操作,导致自增ID持续增长,根源和解决方法如下:
根本原因
你的race_id字段没有设置主键或唯一约束,MySQL无法识别重复的race_id,因此不会触发ON DUPLICATE KEY UPDATE分支,每次都会执行INSERT生成新行,自增ID自然随之增加。另外,你的代码直接拼接变量到SQL中,存在严重的SQL注入风险。
具体解决步骤
1. 给race_id添加唯一约束
首先修改表结构,让MySQL能够识别重复的race_id:
-- 方案1:给race_id添加唯一约束(适合race_id不是主键的场景) ALTER TABLE webpage_race ADD UNIQUE KEY idx_race_id (race_id); -- 方案2:将race_id设为主键(如果它本身是记录的唯一标识) ALTER TABLE webpage_race MODIFY COLUMN race_id INT PRIMARY KEY;
2. 修正PHP代码逻辑并修复SQL注入
改用预处理语句避免注入,同时优化ON DUPLICATE KEY UPDATE的逻辑(更新race_id为自身无意义,仅作为占位触发不插入新行即可):
<?php foreach($race_obj as $key => $race_value){ $race_id = $race_value->race_id ?? null; // 跳过空的race_id记录(如果race_id不允许为null) if(is_null($race_id)){ echo '<p align="center">跳过空race_id的记录<br>'; continue; } // 使用预处理语句,避免SQL注入 $sql = ' INSERT INTO webpage_race (race_id) VALUES (?) ON DUPLICATE KEY UPDATE race_id = race_id -- 占位,仅触发不插入新行逻辑 '; $stmt = $conn->prepare($sql); // 若race_id是字符串类型,把'i'改成's' $stmt->bind_param('i', $race_id); if ($stmt->execute()) { $message = '<p align="center">记录处理成功<br>'; } else { $message = "Error: " . $stmt->error . '<br>'; } echo $message; $stmt->close(); } ?>
补充说明
如果表中有其他需要更新的字段,把ON DUPLICATE KEY UPDATE后的内容替换为实际需要更新的字段,比如:
ON DUPLICATE KEY UPDATE race_name = VALUES(race_name), race_time = VALUES(race_time)
内容的提问来源于stack exchange,提问作者Nikos Kioses
相关产品推荐
相关产品推荐

