MySQL中已设UNIQUE KEY时如何复制无重复记录到新表?
嘿,针对你遇到的这个MySQL去重迁移问题,我整理了几个实用且高效的方案,尤其适合大数据量的场景:
方案1:用INSERT IGNORE快速导入(保留首次出现的非重复记录)
这个方法利用你已有的UNIQUE KEY约束,直接跳过插入时的重复键冲突,操作简单且执行效率高,适合只需要保留每组重复中第一条出现的记录的情况。
步骤:
- 先创建和原表结构完全一致的新表(自动继承原表的UNIQUE KEY、主键等约束):
CREATE TABLE IF NOT EXISTS `users_exam_question_answer_new` LIKE `users_exam_question_answer`;
- 执行插入操作,忽略重复的记录:
INSERT IGNORE INTO `users_exam_question_answer_new` SELECT * FROM `users_exam_question_answer`;
说明:
INSERT IGNORE会自动检测插入时的UNIQUE KEY冲突,一旦发现user_id+exam_id+question_id组合重复的行,就直接跳过这条记录。最终新表只会保留每组重复中最先插入的那条(因为原表自增id是递增的,第一个出现的记录会被成功插入,后续重复项因冲突被忽略)。
方案2:分组筛选后插入(自定义保留规则)
如果你不想只保留第一条,而是需要精确控制保留哪条重复记录(比如最新修改的、分数最高的),可以用分组查询先筛选出目标记录,再插入新表,这个方法灵活性更高。
步骤:
- 同样先创建新表:
CREATE TABLE IF NOT EXISTS `users_exam_question_answer_new` LIKE `users_exam_question_answer`;
- 自定义筛选规则插入,比如这里我们保留每组重复中
user_exam_question_answer_id最大的记录(也就是最后插入的那条):
INSERT INTO `users_exam_question_answer_new` SELECT t.* FROM `users_exam_question_answer` t INNER JOIN ( SELECT `user_id`, `exam_id`, `question_id`, MAX(`user_exam_question_answer_id`) AS max_id FROM `users_exam_question_answer` GROUP BY `user_id`, `exam_id`, `question_id` ) AS grouped ON t.user_exam_question_answer_id = grouped.max_id;
说明:
子查询先按你的UNIQUE KEY三个字段分组,找出每组中最大的自增id(对应最后插入的记录),然后通过关联原表获取这条记录的完整数据并插入新表。如果要保留最新修改的记录,只需要把MAX(user_exam_question_answer_id)换成MAX(modion),再把关联条件改成t.modion = grouped.max_modion即可(如果modion有重复,建议结合id一起过滤,避免多条记录匹配)。
额外注意事项
- 备份优先:操作前一定要先备份原表,避免意外:
CREATE TABLE `users_exam_question_answer_backup` LIKE `users_exam_question_answer`; INSERT INTO `users_exam_question_answer_backup` SELECT * FROM `users_exam_question_answer`; - 高峰避坑:大数据量操作建议在非业务高峰执行,避免锁表影响线上业务。
- 重置自增序列:如果新表不需要继承原表的自增id序列,可以执行
ALTER TABLE users_exam_question_answer_new AUTO_INCREMENT = 1;重置。
内容的提问来源于stack exchange,提问作者satyajit bhowmik
相关产品推荐
相关产品推荐

