批量SQL INSERT:如何仅插入全字段无重复行(无需逐句加WHERE NOT EXISTS)
嘿,这个场景太常见了——几百条INSERT还要每条加WHERE NOT EXISTS确实疯掉,给你几个高效又省时间的方案,不用挨个改语句:
方案1:临时表中转法(通用所有数据库)
这个方法不管你用MySQL、PostgreSQL还是SQL Server都能用,思路是先把所有待插入数据扔到临时表去重,再同步到目标表:
-- 1. 复制目标表结构创建临时表 CREATE TEMPORARY TABLE temp_target LIKE target_table; -- 2. 给临时表加全字段联合唯一约束(让数据库自动帮我们去重) ALTER TABLE temp_target ADD UNIQUE KEY (col1, col2, col3, ...); -- 把所有字段列出来 -- 3. 批量把所有待插入数据塞到临时表,重复的会被自动拦截(不同数据库可能要微调,比如MySQL用INSERT IGNORE,PG用ON CONFLICT DO NOTHING) INSERT IGNORE INTO temp_target (col1, col2, col3, ...) VALUES (val1a, val2a, val3a, ...), (val1b, val2b, val3b, ...), ...; -- 你的几百条数据直接粘这里就行 -- 4. 把临时表中不重复的数据同步到目标表(只写一次WHERE NOT EXISTS就行) INSERT INTO target_table (col1, col2, col3, ...) SELECT col1, col2, col3, ... FROM temp_target WHERE NOT EXISTS ( SELECT 1 FROM target_table t WHERE t.col1 = temp_target.col1 AND t.col2 = temp_target.col2 ... -- 全字段匹配,列一遍所有字段 ); -- 5. 用完临时表可以删掉(可选) DROP TEMPORARY TABLE temp_target;
方案2:INSERT + SELECT 一次性去重对比
如果你的待插入数据本身可能有重复,还需要和目标表对比,直接把所有数据放到子查询里去重,再插入:
INSERT INTO target_table (col1, col2, col3, ...) SELECT DISTINCT val1, val2, val3, ... FROM ( VALUES (val1a, val2a, val3a, ...), (val1b, val2b, val3b, ...), ... -- 所有待插入数据 ) AS temp(val1, val2, val3, ...) WHERE NOT EXISTS ( SELECT 1 FROM target_table t WHERE t.col1 = temp.val1 AND t.col2 = temp.val2 ... -- 全字段匹配,只写一次 );
方案3:数据库专属简化语法(最快最省心)
如果你的数据库支持专属语法,这是最省事儿的,前提是先给目标表加全字段联合唯一约束:
MySQL 用 INSERT IGNORE
-- 先加全字段联合唯一约束(只需要加一次) ALTER TABLE target_table ADD UNIQUE KEY (col1, col2, col3, ...); -- 直接批量插入,重复行自动被忽略 INSERT IGNORE INTO target_table (col1, col2, col3, ...) VALUES (val1a, val2a, val3a, ...), (val1b, val2b, val3b, ...), ...;
PostgreSQL 用 ON CONFLICT DO NOTHING
-- 先加全字段联合唯一约束 ALTER TABLE target_table ADD UNIQUE (col1, col2, col3, ...); -- 批量插入,冲突时啥也不做 INSERT INTO target_table (col1, col2, col3, ...) VALUES (val1a, val2a, val3a, ...), (val1b, val2b, val3b, ...), ... ON CONFLICT (col1, col2, col3, ...) DO NOTHING;
SQL Server 用 MERGE
-- 先加全字段联合唯一约束 ALTER TABLE target_table ADD CONSTRAINT UQ_Target_AllCols UNIQUE (col1, col2, col3, ...); -- 用MERGE匹配,不匹配才插入 MERGE INTO target_table t USING ( VALUES (val1a, val2a, val3a, ...), (val1b, val2b, val3b, ...), ... ) AS source(val1, val2, val3, ...) ON t.col1 = source.val1 AND t.col2 = source.val2 AND ... -- 全字段匹配 WHEN NOT MATCHED THEN INSERT (col1, col2, col3, ...) VALUES (source.val1, source.val2, source.val3, ...);
小提醒:加联合唯一约束前,一定要确保目标表现有数据里没有全字段重复的记录,不然约束会创建失败哦。如果是一次性操作,用完也可以考虑删掉约束(如果不需要长期防重复的话)。
内容的提问来源于stack exchange,提问作者AjaxLoser
相关产品推荐
相关产品推荐

