MERGE
문을 UPSERT
으로 사용하여 새 레코드를 추가하거나 현재 레코드를 업데이트하십시오. 여러 연결 및 여러 문 (스레드 당 하나의 연결 및 문)을 통해 데이터베이스를 구동하는 여러 스레드가 있습니다. 나는 한 번에 50 문장을 배치하고있다.MERGE가 SQL2008의 원자 적 진술입니까?
테스트 도중 duplicate key
번 위반을 당해서 매우 놀랐습니다. 나는 MERGE
이 단일 거래로 수행 될 것이기 때문에 불가능하다고 생각합니까? 아니면 그렇습니까?
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
열쇠 쿼리는 다음과 같습니다
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;
}
}
: 같은
내 자바 코드 보인다 ID
필드에 있습니다.
어떻게 기본 키 (V.ID)를 생성합니까? – Paolo
@Paolo'ALTER TABLE CustomerSpend ADD CONSTRAINT [PK_CustomerSpend] PRIMARY KEY CLUSTERED (ID)'. 더 좋은 방법이 있습니까? – OldCurmudgeon
죄송합니다. 귀하가 쿼리에서 전달한 ID의 실제 값을 의미했습니다. Mikael이 아래에 있습니다. 트랜잭션은 원자 적이지만, 동일한 키를 삽입하려고 시도하는 다중 스레드를 막을 수는 없습니다. – Paolo