【问题标题】:Is it possible to determine which rows are affected by SQL Server UPDATE?是否可以确定哪些行受 SQL Server UPDATE 影响?
【发布时间】:2018-10-04 03:15:52
【问题描述】:

我正在使用 Java 程序更新 SQL Server 2017 数据库。目前,在测试我的 UPDATE 语句时,我没有提交更改 (connection.setAutoCommit(false))。

当我打印出受影响的行数时,计数远低于预期(UPDATE 语句应该更新每一行)。

这里是一些示例代码,演示了我用来发出UPDATE 语句的循环:

    // List of users that need to be updated
    List<User> updatedUsers = new ArrayList<>();

    // Connect to database
    Connection connection = null;
    connection = DataFiles.getServerConnection();
    connection.setAutoCommit(false);

    PreparedStatement preparedStatement = null;

    int rowsAffected = 0;
    final int batchSize = 1000;
    int count = 0;

    // Create an UPDATE statement for each record to be updated
    for (User user : updatedUsers) {

        StringBuilder sql = new StringBuilder(
                "UPDATE USERS SET\n"
        );

        sql.append("USER_TYPE=?,\n")
                .append("FIRST_NAME=?,\n")
                .append("LAST_NAME=?,\n")
                .append("EMAIL_ADDRESS=?\n");
        sql.append("WHERE USER_ID=?");

        // Fill each ?
        preparedStatement = connection.prepareStatement(sql.toString());

        preparedStatement.setString(1, user.getUserTypeId());
        preparedStatement.setString(2, user.getFirstName());
        preparedStatement.setString(3, user.getLastName());
        preparedStatement.setString(4, user.getEmailAddress());
        preparedStatement.setString(5, user.getUserId());
        preparedStatement.addBatch();

        // Submit in batches of 1000
        if (++count % batchSize == 0) {
            rowsAffected += IntStream.of(preparedStatement.executeBatch()).sum();
            preparedStatement.clearBatch();
        }
    }
    System.out.println(count);

    rowsAffected += IntStream.of(preparedStatement.executeBatch()).sum();
    preparedStatement.clearBatch();
    preparedStatement.close();

    System.out.println(rowsAffected + " rows affected!");

我的 WHERE 语句应该与循环的每次传递都匹配一条记录,但我得到的是 33 rows affected 而不是我期望的 32,000。

有没有办法返回受影响的行?我想将匹配项与不匹配项进行比较。

我已经尝试将我的循环调整为具有相同 WHERE 标准的 SELECT 语句并返回所有 32,000 条记录,所以我确信这些记录确实存在。 p>

【问题讨论】:

  • @Nick - 有可能,但不太可能。实际上,我不希望所有 32,000 行都更新,但比 33 多得多。但这就是为什么我想知道哪些行受到影响,以便找出原因。
  • 这是一个生产数据库,所以我想在提交更新之前说服自己它是准确的。
  • 您是否知道在代码的最后只打印一次rowsAffected?您如何检查每批后的更新计数?
  • @TimBiegeleisen - 是的,但我会在每次批量更新时添加到 rowsAffected。所以我在打印时的假设是,这将反映每批受影响的所有行。
  • @TimBiegeleisen 今天我学到了一些新东西。

标签: java sql sql-server


【解决方案1】:

您正在循环的每次迭代中创建一个新的 PreparedStatement。您需要在调用 executeBatch 的同一个preparedStatement 对象上将批处理执行排队。目前,您只执行第 1000 个排队查询。

StringBuilder sql = new StringBuilder(
    "UPDATE USERS SET\n"
);

sql.append("USER_TYPE=?,\n")
    .append("FIRST_NAME=?,\n")
    .append("LAST_NAME=?,\n")
   .append("EMAIL_ADDRESS=?\n");
sql.append("WHERE USER_ID=?");

preparedStatement = connection.prepareStatement(sql.toString());

for (User user : updatedUsers) {
        preparedStatement.setString(1, user.getUserTypeId());
        preparedStatement.setString(2, user.getFirstName());
        preparedStatement.setString(3, user.getLastName());
        preparedStatement.setString(4, user.getEmailAddress());
        preparedStatement.setString(5, user.getUserId());
        preparedStatement.addBatch();

        // Submit in batches of 1000
        if (++count % batchSize == 0) {
            rowsAffected += IntStream.of(preparedStatement.executeBatch()).sum();
            preparedStatement.clearBatch();
        }
}

为了确定受影响的行(在 sql server 2005+ 中),您可以在 SQL 中使用 OUTPUT 子句让数据库返回受影响的行数据。 Article

【讨论】:

  • 这确实解决了我遇到的问题,非常感谢!但它实际上并没有回答如何检索受影响的行的问题。
  • 更新了我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-07
  • 2010-10-26
  • 2023-03-31
  • 1970-01-01
  • 2017-05-25
  • 2013-01-08
相关资源
最近更新 更多