Решения для вставки дубликатов ключей - PullRequest
1 голос
/ 21 июля 2009

НЕТ ответов MySQL, пожалуйста!

Основной запрос выглядит следующим образом (предположим, что A - это ключ)

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

Источник содержит много записей, которые могут быть, а могут и не находиться в месте назначения, что означает, что вставка завершится неудачно, как только обнаружится дублирующаяся запись.

Желаемое поведение: INSERT или IGNORE

Это желаемый сценарий для данной проблемы. Вставьте, если можете, в противном случае продолжите.

Pseudo 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 ]

2 голосов
/ 21 июля 2009

Некоторые базы данных предоставляют явный синтаксис для операций, которые включают условную вставку / обновление / игнорирование.

Oracle и SQLServer , например, имеют оператор 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 голос
/ 21 июля 2009

Если вы используете общий первичный ключ:

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 );
0 голосов
/ 21 июля 2009

Если вы используете 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.

0 голосов
/ 21 июля 2009

Я бы, вероятно, сделал следующее:

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
...