2009-07-20 39 views
1

沒有MySQL的答案請!插入重複密鑰的解決方案

的基本查詢如下(假設A是關鍵)

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

源包含多條記錄,可能會或可能不會已經在目的地,這意味着插入就會失敗的重複記錄遇到。

所需的行爲:INSERT或忽略

這是給定的問題所需的方案。如果可以,請插入,否則繼續。

僞C#/ java的:通過增加

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

到查詢結束

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

這可以在SQL處理 - 換句話說,檢查插入之前。

處理這種常見情況的其他方法有哪些?這些技術的優點和缺點是什麼?

+0

你總是可以讓A成爲主鍵? – 2009-07-20 20:53:23

回答

2

有些數據庫提供涉及有條件的插入/更新操作的明確語法/忽略。

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

如果共用一個主鍵:如果你不

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); 
+1

比較a1 + b1 + c1與a + b + c幾乎肯定是一個壞主意。如果這些值是:a1 = 1,b1 = 2,c1 = 3,a = 2,b = 3,c = 1?更不用說連接或添加這些列可能會破壞索引的使用而導致性能損失。 – 2009-07-20 22:36:39

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 
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的優勢。

+0

MySQL在它的非標準SQL中有一些很好的功能。如果其他供應商複製它們會很好。 – 2009-07-22 20:37:51