2009-07-20 4 views
1

AUCUNE réponse MySQL ne vous plait!Solutions pour l'insertion de clés dupliquées

La requête de base est la suivante (en supposant A est la clé)

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

Source contient de nombreux enregistrements qui peuvent ou peuvent ne pas être déjà à destination, ce qui signifie que l'insert échouera dès qu'un enregistrement en double est rencontré.

Comportement souhaité: INSERT ou IGNORE

Ceci est le scénario souhaité pour le problème donné. Insérez si vous le pouvez, sinon continuez.

Pseudo C#/java:

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

Cela peut être manipulé dans SQL en ajoutant

AND NOT EXISTS (SELECT A FROM destination INNER JOIN source on destination.A = source.a1) 

à la fin de la requête - En d'autres termes, vérifier avant d'insérer.

Quelles sont les autres alternatives à la gestion de cette situation courante? Quels sont les avantages et les inconvénients de ces techniques?

+0

Vous pouvez toujours faire de A une clé primaire? –

Répondre

2

Certaines base de données fournissent une syntaxe explicite pour les opérations qui impliquent un insert conditionnel/mise à jour/ignorer.

Oracle et SQLServer, par exemple ont l'instruction MERGE qui peut insérer/mettre à jour/supprimer/ignorer un enregistrement basé sur un ensemble de prédicats.

Ignorer la syntaxe spécifique à la base de données, vous pouvez effectuer l'insertion en utilisant un prédicat qui exclut les enregistrements qui existent déjà:

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

Si vous partagez une clé primaire commune:

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

Si vous n'êtes pas:

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

Comparer a1 + b1 + c1 à a + b + c est presque certainement une mauvaise idée. Que se passerait-il si les valeurs étaient: a1 = 1, b1 = 2, c1 = 3, a = 2, b = 3, c = 1? Sans oublier la perte de performance en concaténant ou en ajoutant ces colonnes pouvant ruiner l'utilisation des index. –

0

Je probablement faire ce qui suit:

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 
0

Si vous êtes en utilisant MySQL et avez le luxe de forcer des clés non dupliquées en utilisant un index UNIQUE, vous pouvez utiliser INSERT ON DUPLICATE KEY UPDATE avec une mise à jour idempotente (non-op) pour les doublons.

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

Cela a l'avantage d'être très rapide et ne nécessitant pas un SELECT supplémentaire.

+0

MySQL a quelques fonctionnalités intéressantes dans son SQL non standard. Ce serait bien si d'autres vendeurs les copiaient. –

Questions connexes