当前位置: 首页 > 面试题库 >

MERGE是SQL2008中的原子语句吗?

颛孙钱青
2023-03-14
问题内容

我正在使用一条MERGE语句UPSERT来添加新记录或更新当前记录。我有多个线程通过多个连接和多个语句(每个线程一个连接和一个语句)来驱动数据库。我一次要批处理50个语句。

我很惊讶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字段上的键。


问题答案:

MERGE 是原子的,意味着所有更改都已提交或所有更改都已回滚。

在高并发的情况下,它不能防止重复的密钥。添加holdlock提示将解决这一问题。

MERGE INTO CustomerSpend WITH (HOLDLOCK) 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 );


 类似资料:
  • 下面是我在Snowflake1中实现merge with stream的步骤。创建一个表create或replace表employee(employee_id number,salary number,manager_id number);2.创建流。在表employees上创建或替换流employees_stream3.创建消费者表。创建或替换表employees_consumer(employ

  • 问题内容: 我正在尝试在Go中执行MERGE语句: 但是我得到了这个错误: 在MySQL中也是如此: 怎么了? 问题答案: 不支持,等效的是 插入…在重复的密钥更新上 尝试这个, 但请确保将其设置为或。

  • 问题内容: 源表 目标表 合并后 我正在使用此SQL 这会导致错误 消息8672,级别16,状态1,第18行 MERGE语句尝试多次更新或删除同一行。当目标行与多个源行匹配时,就会发生这种情况。MERGE语句不能多次更新/删除目标表的同一行。优化ON子句以确保目标行最多匹配一个源行,或使用GROUP BY子句对源行进行分组。 我想用三个匹配值中的任何一个用地址值更新A中的行。这该怎么做? 问题答案

  • 问题内容: 我正在进行大量CRUD操作,并在CUD之外创建合并存储过程。我存储的过程看起来像这样 当我执行此操作时,我得到了这个完整的错误 消息10714,级别15,状态1,过程usp_AdministrationHistoryMerge,第36行在MERGE语句的“ UPDATE”子句中,“ WHEN MATCHED”类型的动作不能出现多次。 我四处寻找SO,并找到了解决此问题的几种方法,但是我

  • 本文向大家介绍DBMS中的SELECT语句及其子句,包括了DBMS中的SELECT语句及其子句的使用技巧和注意事项,需要的朋友参考一下 select语句用于根据条件从数据库中获取所需的数据(如果有)。该数据以表格的形式返回。 select语句的基本语法是- select语句的一个示例是- <学生> 学生号码 学生姓名 学生电话 学生分数 学生_主修 科目 1 安德鲁 6615927284 95 文