MERGE
ステートメントをUPSERT
として使用して、新しいレコードを追加するか、現在のレコードを更新します。私は複数の接続と複数のステートメント(スレッドごとに1つの接続とステートメント)を介してデータベースを駆動する複数のスレッドを持っています。私は一度に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
@Paolo 'ALTER TABLE CustomerSpend ADD CONSTRAINT [PK_CustomerSpend] PRIMARY KEY CLUSTERED(ID)'。より良い方法がありますか? – OldCurmudgeon
申し訳ありませんが、私はあなたがクエリで渡していたIDの実際の値を意味しました。 Mikaelさんが下にあります。トランザクションはアトミックですが、同じキーを挿入しようとしている複数のスレッドを停止するものはありません。 – Paolo