【问题标题】:Return number of rows affected by SQL UPDATE statement in Java返回 Java 中受 SQL UPDATE 语句影响的行数
【发布时间】:2020-03-12 21:43:12
【问题描述】:

我正在使用 MySQL 数据库并通过 Java 访问它。

PreparedStatement prep1 = this.connection.prepareStatement(
        "UPDATE user_table 
        SET Level = 'Super' 
        WHERE Username = ?");
prep1.setString(1, username);

上面的更新语句工作正常,但是我想获取受此语句影响的行数。请问这样可以吗?

【问题讨论】:

    标签: java mysql sql prepared-statement rowcount


    【解决方案1】:
    根据 JDBC 规范,

    Statement.executeUpdate()execute() 后跟 getUpdateCount() 将返回行数匹配,而不是更新。如果您想要更新的计数,可以将useAffectedRows=true 指定为non-standard URL option。更多信息请见here

    【讨论】:

    • @amaidment:感谢您告诉我。我将链接替换为 Internet 档案中的链接。
    【解决方案2】:

    在 PreparedStatement 上调用 executeUpdate() 应该返回一个 int,即更新记录的数量。

    【讨论】:

    • 其实我有这个问题。当我对值为 X 的列运行更新并尝试将其更新为 X 时,原始 mysql 查询返回 0,因为行受到影响但 java 准备语句返回行数,即使 X 从未改变。
    • 这实际上不是更新记录的数量,不幸的是匹配记录的数量。在我的设置(MySQL)中,当我将一个值更新为相同的值时,executeUpdate() 的返回值得到 1,但是当我在 Workbench 中手动运行查询时,它显示:0 行受影响行匹配:1 已更改: 0 警告: 0
    • 如果查询是 UPDATE 并且更新的记录数是 0,它仍然会返回 1,而预期的答案是 0。
    • 不正确。对于读者:向下滚动并检查特雷弗的答案。 getUpdateCount() 是问题的关键。
    【解决方案3】:
    1. 首先,使用以下构造函数准备“PreparedStatement”对象:

      PreparedStatement pStmt = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
      //here variable 'sql' is your query ("UPDATE user_table SET Level = 'Super' WHERE Username = ?") 
      
    2. 然后,将您的参数设置为“pStmt”。在这种情况下:

      prep1.setString(1, username);
      
    3. 最后,执行更新并将受影响的行作为整数获取

      int affectedRows = pStmt.executeUpdate();
      

    【讨论】:

      【解决方案4】:

      刚刚看到另一个类似情况,我只想在确实发生变化的情况下做额外的工作,我认为最中立的方法是更改​​查询以排除设置字段的情况匹配:

      UPDATE user_table SET Level = 'Super' WHERE Username = ? AND Level <> 'Super'
      

      【讨论】:

      • 这如何回答 OP 的问题?
      • 很简单,您必须在 where 子句中添加额外的条件来限制返回的行数与受影响的行数相同。 (至少可以在他的 java 客户端中工作)
      • 我明白了。我要说的问题是如何 在Java 中取回该数字。您的答案没有解释这一点(查看接受的答案,确实解释了这一点)。但是,从 cmets 看来,您的答案似乎是已接受答案的一个很好的补充。
      【解决方案5】:

      可以使用 SQL%ROWCOUNT (For ORACLE) 或 @@ROWCOUNT(FOR SQL SERVER) 返回受 SQL 更新影响的行数

      注意:为了返回更新、删除等的行数。我们必须在存储过程中使用 OUT 参数来存储更新、删除等的行数。

      1. 要获取更新、删除等的行数,我们必须使用 Java中的registerOutParameter方法

      2. 将更新或删除的行数等存储到其中一个 存储过程中的OUT参数我们必须设置它的类型 在执行命令之前在我们的脚本中添加参数。 (的情况下 更新或删除它将是 NUMERIC)

      3. 一旦命令执行,存储更新或删除的值 行到变量中(它可以是新变量或变量 在类等中可用。)通过调用该参数的索引 (例如:如果存储过程中的 OUT 参数为 A=cs.getInt(3) 第二个参数)

      4. 现在,变量的值是更新或删除的行 (即 A=10)

      存储瓷器示例

      Function demo( A varchar2(10), B OUT NUMBER)RETURN NUMBER IS EXIST_LP NUMBER;
      BEGIN
      UPDATE demo_temp SET name=A where name="ABC";
      B:=SQL%ROWCOUNT -- total number of rows updated
      RETRUN EXIST_LP;
      END demo;
      

      java 脚本示例

      public void update(demo demo){
      int rowCount = 0;
      Connection conn = null;
      CallableStatement cs = null;
      try{
      InitialContext ctx = new InitialContext();
      DataSource ds = (DataSource) ctx.lookup("your data source path");
      conn = ds.getConnection();
      cs = conn.prepareCall("BEGIN ? :=demo_dbp.demo(?,?) ); END;"); // stored proc
      cs.registerOutParameter(1, Types.INTEGER);
      cs.setString(2, "XYZ");
      cs.registerOutParameter(3, Types.NUMERIC);
      rowCount=cs.execcuteUpdate();
      demo.setUpdateCount(cs.getInt(3));
      } catch (SQLException exc) {
        throw new DaoException("An SQL Exception has occurred.", exc);
      } catch (NamingException ne) {
        throw new DaoException("A Naming Exception has occurred.", ne);
      } catch (Exception e) {
        throw new DaoException("An Exception has occurred", e);
      } finally {
      
        try {
                  if (cs != null) {
                      cs.close();
                  }
      } catch (SQLException ex1) {
      }
      try {
                  if (conn != null) {
                      conn.close();
                  }
      } catch (SQLException ex) {
      }
      
      }
      }
      

      注意: executeUpdate() 不返回更新或删除的行数。它只返回 0 或 1。

      1. 0--执行失败
      2. 1--执行成功

      【讨论】:

        【解决方案6】:

        运行查询时会返回该数字:

        int rows = prep1.executeUpdate(); 
        System.out.printf("%d row(s) updated!", rows); 
        

        【讨论】:

          【解决方案7】:

          如果需要知道有多少行会受到影响而不执行它,则必须先运行 SELECT 语句。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-01-08
            • 2010-10-26
            • 2017-01-02
            • 1970-01-01
            • 2011-09-07
            • 1970-01-01
            • 1970-01-01
            • 2019-04-24
            相关资源
            最近更新 更多