插入重复键的解决方案

时间:2009-07-20 20:50:14

标签: sql insert bulkinsert

没有MySQL的答案!

基本查询如下(假设A为Key)

INSERT INTO destination (A,B,C)
SELECT a1,b1,c1 
FROM source
WHERE (selectconditions) ; 

Source包含许多可能已经或可能不在目的地的记录,这意味着一旦遇到重复记录,插入就会失败。

所需行为:INSERT或IGNORE

  

这是给定问题的理想方案。如果可以,请插入,否则继续。

伪c#/ java:

foreach(record in selectQuery) 
{  
   try { destination.insert(record) } 
   catch(insertionException){//squelch} 
}

这可以通过添加

在SQL中处理
AND NOT EXISTS (SELECT A FROM destination INNER JOIN source on destination.A = source.a1) 

到查询结尾 - 换句话说,在插入之前检查。

处理这种常见情况有哪些其他替代方案?这些技术的优点和缺点是什么?

4 个答案:

答案 0 :(得分:2)

某些数据库为涉及条件insert / update / ignore的操作提供了显式语法。

例如,

OracleSQLServer具有MERGE语句,该语句可以基于一组谓词插入/更新/删除/忽略记录。

忽略特定于数据库的语法,您可以使用排除已存在记录的谓词来执行插入:

INSERT INTO target( A, B, C )
SELECT SA, SB, SB FROM source
WHERE NOT EXISTS (select A, B, C from TARGET where A = SA, B = SB, C = SC)

答案 1 :(得分:1)

如果您共享一个公共主键:

INSERT INTO destination 
( A, B, C)
SELECT a1, b1, c1 FROM source
WHERE source.pk not in ( SELECT pk FROM destination );

如果你不这样做:

INSERT INTO destination 
( A, B, C)
SELECT a1, b1, c1 FROM source
WHERE a1 + b1 + c1 not in ( SELECT a+b+c FROM destination );

答案 2 :(得分:0)

我可能会做以下事情:

INSERT INTO Target (A, B, C)
SELECT
     S.A, S.B, S.C
FROM
     Source S
LEFT OUTER JOIN Target T ON
     T.A = S.A AND
     T.B = S.B AND
     T.C = S.C
WHERE
     T.A IS NULL

答案 3 :(得分:0)

如果您正在使用MySQL并且可以使用UNIQUE索引强制使用非重复键,则可以使用INSERT ON DUPLICATE KEY UPDATE对重复项进行幂等(无操作)更新。

INSERT INTO Target (A, B, C) (SELECT a1, b1, c1 FROM Source) ON DUPLICATE KEY UPDATE A=A;

这样做的好处是速度非常快,不需要额外的SELECT