归档表数据迁移:插入时忽略重复数据解决唯一约束报错
解决唯一约束下仅插入新增记录的问题
这个场景在数据归档合并时太常见了,不同数据库有对应的简洁方案,我给你分情况说明:
MySQL/MariaDB 方案
1. 直接忽略冲突行
用 INSERT IGNORE 语法,它会自动跳过那些触发唯一约束的重复行,只插入表1中没有的记录:
INSERT IGNORE INTO table1 (col1, col2, col3, ...) SELECT col1, col2, col3, ... FROM table2;
注意:这个语句会忽略所有插入错误(不止唯一约束),如果你的场景里有其他需要关注的错误,谨慎使用。
2. 明确跳过冲突(更安全)
如果不想忽略所有错误,而是仅针对唯一约束做跳过,可以用 ON DUPLICATE KEY UPDATE,把冲突行的字段设为自身原值(相当于不做任何更新):
INSERT INTO table1 (col1, col2, col3, ...) SELECT col1, col2, col3, ... FROM table2 ON DUPLICATE KEY UPDATE col1 = table1.col1;
PostgreSQL 方案
PostgreSQL 没有 INSERT IGNORE,但可以用 ON CONFLICT DO NOTHING 精准处理唯一约束冲突:
INSERT INTO table1 (col1, col2, col3, ...) SELECT col1, col2, col3, ... FROM table2 ON CONFLICT (unique_column_name) DO NOTHING;
如果是复合唯一约束(多个字段组成的唯一键),把括号里的列改成所有约束字段即可,比如 ON CONFLICT (col1, col2) DO NOTHING。
SQL Server 方案
1. 使用 MERGE 语句(推荐)
MERGE 是SQL Server专门用来处理源表和目标表匹配/不匹配场景的语法,非常适合这种合并插入需求:
MERGE INTO table1 AS target USING (SELECT col1, col2, col3, ... FROM table2) AS source ON target.unique_column = source.unique_column WHEN NOT MATCHED THEN INSERT (col1, col2, col3, ...) VALUES (source.col1, source.col2, source.col3, ...);
2. 简单场景用 WHERE NOT EXISTS
如果逻辑不复杂,也可以用子查询判断是否存在重复,再插入:
INSERT INTO table1 (col1, col2, col3, ...) SELECT col1, col2, col3, ... FROM table2 WHERE NOT EXISTS ( SELECT 1 FROM table1 WHERE table1.unique_column = table2.unique_column );
复合唯一约束的话,在子查询的WHERE里把所有约束字段都加上匹配条件就行。
通用注意事项
- 一定要明确你的唯一约束对应的是哪些字段,所有方案都依赖这个来判断“重复”;
- 操作前建议先用
SELECT ... FROM table2 WHERE NOT EXISTS (...)预览一下要插入的行,确认数据没问题再执行插入; - 涉及数据操作前,最好先备份表数据,避免意外情况。
内容的提问来源于stack exchange,提问作者Jey
相关产品推荐
相关产品推荐

