2011-10-13 55 views
0

標題非常清晰... 我希望能夠添加一個項目到數據庫,並且如果已經有一個項目匹配唯一的列,返回該項目的ID ......因爲我發現一個解決方案JDBC - 插入並返回生成的ID,或者如果DUPLICATE KEY返回舊ID

下面的表達式是接近

INSERT INTO table (a,b,c) VALUES (1,2,3) 
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3; 

我能夠獲取新的ID using語句(插入新行時) .generatedKeys()。 如果重複,會在statement.generatedKeys()中出現「id」?如果不是,我該如何取回它?

UPDATE:使用存儲過程,下面是正是我需要的:

INSERT INTO applications (path, displayName) VALUES (?, ?) 
ON DUPLICATE KEY UPDATE 
    id = LAST_INSERT_ID(id), path = ?, displayName = ?; 
SELECT LAST_INSERT_ID() INTO ?; 

它適用於不同的項目我的工作,它使用的MySQL連接器在.NET中,但不幸的是存儲過程在這個Java項目中對我來說不是一種選擇。

有沒有其他方法可以在同一網絡旅程中發送2條語句?

回答

2

這似乎是合法的

INSERT INTO table (a,b,c) VALUES (1,2,3) 
ON DUPLICATE KEY UPDATE c=3; 

,但是這太瘋狂了:

INSERT INTO table (a,b,c) VALUES (1,2,3) 
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3; 

你更新現有記錄的ID字段?這些記錄涉及到這個記錄會發生什麼?

無論如何,如果正常更新(最差的)statement.generatedKeys()不會返回已經存在的ID。 在這種情況下,您可能需要發出額外的select語句(使用where子句中的唯一鍵列:select id from table where a=1 and b=2)來查找記錄的ID。

或者,您也可以編寫一個存儲過程,在這兩種情況下插入/更新都會返回ID。

+0

我沒有reffering到上面的EXACT示例中,我只是聲明INSERT INTO ... ON DUPLICATE KEY通常可以幫助我完成要查找的內容 –

+0

使用存儲過程對我來說不是一種選擇,JDBC中是否有執行的方法來執行一次網絡旅程中的兩條語句? –

0

如果您的目標是防止重複記錄,您可以使用主鍵/ UNIQUE constraint設置表格。然後,您可以拿在下列代碼路徑之一:

  1. 編程方式檢查了你要添加和處理,其中該行已經存在於表
  2. 嘗試的情況下該行的唯一性插入新行。如果它是重複的,那麼嘗試將會失敗並出現異常,您可以使用相同的標準找到舊行。我認爲這是一個糟糕的做法。
2

所以我只是和OP有相同的要求。 Mysql處理INSERT ... ON DUPLICATE KEY UPDATE的方式只是asinine,但不幸的是我們必須忍受它。當您在Mysql 5.5或更高版本上使用ON DUPLICATE時,如果插入發生時沒有重複,則JDBC將返回1的計數和新插入行的ID。如果由於重複而採取的操作是更新,則即使新的ID從未實際插入到表中,JDBC也會返回2的計數以及原始行的ID和新生成的ID。

您可以通過調用PreparedStatement.getGeneratedKeys()來獲取正確的密鑰。第一個關鍵是幾乎總是一個你有興趣因此,與上面的例子:

通過調用
INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=3; 

你可以得到插入或更新ID:

Long key; 
ResultSet keys = preparedStatement.getGeneratedKeys(); 
if (keys.next()) 
    key = keys.getLong("GENERATED_KEY"); 
+0

確實看起來像2個ID在重複時添加。我不能只使用第一個,因爲我試圖一次插入許多行,並且這個「額外從未使用過的id」會將所有內容都擰緊。 – StackExploded