我使用MERGE
語句作爲UPSERT
來添加新記錄或更新當前的記錄。我有多個線程通過多個連接和多個語句(每個線程一個連接和語句)來驅動數據庫。我一次批量陳述50。MERGE是SQL2008中的一個原子語句嗎?
我很驚訝在我的測試中得到duplicate key
違規。我預計這是不可能的,因爲MERGE
將作爲單個交易執行,還是它?
我的Java代碼如下所示:
private void addBatch(Columns columns) throws SQLException {
try {
// Set parameters.
for (int i = 0; i < columns.size(); i++) {
Column c = columns.get(i);
// Column type is an `enum` with a `set` method appropriate to its type, e.g. setLong, setString etc.
c.getColumnType().set(statement, i + 1, c.getValue());
}
// Add the insert as a batch.
statement.addBatch();
// Ready to execute?
if (++batched >= MaxBatched) {
statement.executeBatch();
batched = 0;
}
} catch (SQLException e) {
log.warning("addBatch failed " + sql + " thread " + Thread.currentThread().getName(), e);
throw e;
}
}
查詢看起來是這樣的:
MERGE INTO CustomerSpend AS T
USING (SELECT ? AS ID, ? AS NetValue, ? AS VoidValue) AS V
ON T.ID = V.ID
WHEN MATCHED THEN
UPDATE SET T.ID = V.ID, T.NetValue = T.NetValue + V.NetValue, T.VoidValue = T.VoidValue + V.VoidValue
WHEN NOT MATCHED THEN
INSERT (ID,NetValue,VoidValue) VALUES (V.ID, V.NetValue, V.VoidValue);
錯誤讀取:
java.sql.BatchUpdateException: Violation of PRIMARY KEY constraint 'PK_CustomerSpend'. Cannot insert duplicate key in object 'dbo.CustomerSpend'. The duplicate key value is (498288 ).
at net.sourceforge.jtds.jdbc.JtdsStatement.executeBatch(JtdsStatement.java:944)
at x.db.Db$BatchedStatement.addBatch(Db.java:299)
...
在桌子上,關鍵是PRIMARY
關鍵在ID
字段。
你是如何生成主鍵(V.ID)? – Paolo 2012-03-26 12:02:20
@Paolo'ALTER TABLE CustomerSpend ADD CONSTRAINT [PK_CustomerSpend] PRIMARY KEY CLUSTERED(ID)'。有沒有更好的辦法? – OldCurmudgeon 2012-03-26 12:37:05
對不起,我的意思是您在查詢中傳遞的ID的實際值。 Mikael的下面 - 交易是原子的,但沒有什麼能阻止多個線程試圖插入相同的密鑰 – Paolo 2012-03-26 21:31:00