繁体   English   中英

如何在 Java 中使用 ResultSet 获取行数?

[英]How to get row count using ResultSet in Java?

我正在尝试创建一个简单的方法,该方法接收一个 ResultSet 作为参数并返回一个包含 ResultSet 行计数的 int。 这是一种有效的方法吗?

int size = 0;
    try {
        while(rs.next()){
            size++;
        }
    }
    catch(Exception ex) {
        System.out.println("------------------Tablerize.getRowCount-----------------");
        System.out.println("Cannot get resultSet row count: " + ex);
        System.out.println("--------------------------------------------------------");
    }

我试过这个:

int size = 0;
try {
    resultSet.last();
    size = resultSet.getRow();
    resultSet.beforeFirst();
}
catch(Exception ex) {
    return 0;
}
return size;

但是我收到一条错误消息,指出com.microsoft.sqlserver.jdbc.SQLServerException: The requested operation is not supported on forward only result sets.

在此先感谢您的指点!

如果您有权访问导致此结果集的准备好的语句,则可以使用

connection.prepareStatement(sql, 
  ResultSet.TYPE_SCROLL_INSENSITIVE, 
  ResultSet.CONCUR_READ_ONLY);

这以一种您可以倒回光标的方式准备您的语句。 这也记录在ResultSet Javadoc 中

然而,一般来说,对于大型结果集,前向和后退游标可能效率很低。 SQL Server 中的另一个选项是直接在 SQL 语句中计算总行数:

SELECT my_table.*, count(*) over () total_rows
FROM my_table
WHERE ...

您的 sql 语句创建代码可能类似于

statement = connection.createStatement();

解决“com.microsoft.sqlserver.jdbc.SQLServerException:仅转发结果集不支持请求的操作”异常更改上面的代码

statement = connection.createStatement(
    ResultSet.TYPE_SCROLL_INSENSITIVE, 
    ResultSet.CONCUR_READ_ONLY);

以上更改后,您可以使用

int size = 0;
try {
    resultSet.last();
    size = resultSet.getRow();
    resultSet.beforeFirst();
}
catch(Exception ex) {
    return 0;
}
return size;

获取行数

Statement s = cd.createStatement();
ResultSet r = s.executeQuery("SELECT COUNT(*) AS rowcount FROM FieldMaster");
r.next();
int count = r.getInt("rowcount");
r.close();
System.out.println("MyTable has " + count + " row(s).");

有时 JDBC 不支持以下方法会出现类似“TYPE_FORWARD_ONLY”的错误,请使用此解决方案

JDBC 中不支持 Sqlite。

resultSet.last();
size = resultSet.getRow();
resultSet.beforeFirst();

所以当时使用这个解决方案。

谢谢..

我刚刚做了一个getter方法。

public int getNumberRows(){
    try{
       statement = connection.creatStatement();
       resultset = statement.executeQuery("your query here");
       if(resultset.last()){
          return resultset.getRow();
       } else {
           return 0; //just cus I like to always do some kinda else statement.
       }
    } catch (Exception e){
       System.out.println("Error getting row count");
       e.printStackTrace();
    }
    return 0;
}

改为执行SELECT COUNT(*) FROM ...查询。

如果您有表并将 ID 存储为主要和自动增量,那么这将起作用

获取总行数的示例代码http://www.java2s.com/Tutorial/Java/0340__Database/GettheNumberofRowsinaDatabaseTable.htm

下面是代码

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;

public class Main {
  public static void main(String[] args) throws Exception {
    Connection conn = getConnection();
    Statement st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
        ResultSet.CONCUR_UPDATABLE);

    st.executeUpdate("create table survey (id int,name varchar(30));");
    st.executeUpdate("insert into survey (id,name ) values (1,'nameValue')");
    st.executeUpdate("insert into survey (id,name ) values (2,null)");
    st.executeUpdate("insert into survey (id,name ) values (3,'Tom')");
    st = conn.createStatement();
    ResultSet rs = st.executeQuery("SELECT * FROM survey");

    rs = st.executeQuery("SELECT COUNT(*) FROM survey");
    // get the number of rows from the result set
    rs.next();
    int rowCount = rs.getInt(1);
    System.out.println(rowCount);

    rs.close();
    st.close();
    conn.close();

  }

  private static Connection getConnection() throws Exception {
    Class.forName("org.hsqldb.jdbcDriver");
    String url = "jdbc:hsqldb:mem:data/tutorial";

    return DriverManager.getConnection(url, "sa", "");
  }
}

其他人已经回答了如何解决您的问题,所以我不会重复已经说过的内容,但我会这样说:您可能应该在阅读之前不知道结果集计数的情况下找出解决问题的方法结果。

在读取结果集之前实际需要行计数的情况很少,尤其是在像 Java 这样的语言中。 我认为需要行计数的唯一情况是当行计数是您需要的唯一数据时(在这种情况下,计数查询会更好)。 否则,最好使用包装器对象来表示表数据,并将这些对象存储在动态容器(如 ArrayList)中。 然后,一旦结果集被迭代,您就可以获得数组列表计数。 对于需要在读取结果集之前知道行数的每个解决方案,您可能会想到一个解决方案,它在读取之前不知道行数而无需太多努力。 通过考虑在处理之前绕过需要知道行数的解决方案,您可以省去 ResultSet 滚动到结果集末尾然后回到开头的麻烦(这对于大型结果集来说可能是一项非常昂贵的操作) .

当然,现在我并不是说在读取结果集之前您可能需要行计数。 我只是说在大多数情况下,当人们认为他们在阅读之前需要结果集计数时,他们可能不需要,并且值得花 5 分钟考虑是否有其他方法。

只是想在这个主题上提供我的 2 美分。

您的函数将返回 ResultSet 的大小,但它的光标将设置在最后一条记录之后,因此如果不通过调用 beforeFirst()、first() 或 previous() 来回绕它,您将无法读取其行,并回绕方法不适用于前向 ResultSet(您将获得与在第二个代码片段中获得的相同的异常)。

大多数驱动程序只支持前向结果集 - 所以不支持像 last、beforeFirst 等方法。

如果您也在同一个循环中获取数据,则第一种方法是合适的 - 否则 resultSet 已经被迭代并且不能再次使用。

在大多数情况下,要求是在不获取行的情况下获取查询将返回的行数。 遍历结果集以查找行数与处理数据几乎相同。 最好再执行一次 count(*) 查询。

以下两个选项对我有用:

1) 返回结果集中行数的函数。

private int resultSetCount(ResultSet resultSet) throws SQLException{
    try{
        int i = 0;
        while (resultSet.next()) {
            i++;
        }
        return i;
    } catch (Exception e){
       System.out.println("Error getting row count");
       e.printStackTrace();
    }
    return 0;
}

2) 使用 COUNT 选项创建第二条 SQL 语句。

ResultSet具有根据提供的选项来回移动光标的方法。 默认情况下,它是向前移动的( TYPE_FORWARD_ONLY ResultSet类型)。 除非 CONSTANTS 正确指示ResultSet滚动性和更新,否则您最终可能会收到错误消息。 例如beforeLast()如果结果集不包含行,则此方法无效。 如果不是TYPE_FORWARD_ONLY则抛出错误。

检查是否获取空行的最佳方法 --- 在检查不存在后插入新记录

if( rs.next() ) {

   Do nothing
} else {
  No records fetched!
}

这里

这里有一些代码可以避免获取计数来实例化数组,而是使用 ArrayList 并且在返回之前将 ArrayList 转换为所需的数组类型。

请注意,此处的 Supervisor 类实现了 ISupervisor 接口,但在 Java 中,您不能将 object[](ArrayList 的普通 toArray() 方法返回)转换为 ISupervisor[](我认为您可以在 C# 中做到),所以您必须遍历所有列表项并填充结果数组。

/**
 * Get Supervisors for given program id
 * @param connection
 * @param programId
 * @return ISupervisor[]
 * @throws SQLException
 */
public static ISupervisor[] getSupervisors(Connection connection, String programId)
  throws SQLException
{
  ArrayList supervisors = new ArrayList();

  PreparedStatement statement = connection.prepareStatement(SQL.GET_SUPERVISORS);
  try {
    statement.setString(SQL.GET_SUPERVISORS_PARAM_PROGRAMID, programId);
    ResultSet resultSet = statement.executeQuery();  

    if (resultSet != null) {
      while (resultSet.next()) {
        Supervisor s = new Supervisor();
        s.setId(resultSet.getInt(SQL.GET_SUPERVISORS_RESULT_ID));
        s.setFirstName(resultSet.getString(SQL.GET_SUPERVISORS_RESULT_FIRSTNAME));
        s.setLastName(resultSet.getString(SQL.GET_SUPERVISORS_RESULT_LASTNAME));
        s.setAssignmentCount(resultSet.getInt(SQL.GET_SUPERVISORS_RESULT_ASSIGNMENT_COUNT));
        s.setAssignment2Count(resultSet.getInt(SQL.GET_SUPERVISORS_RESULT_ASSIGNMENT2_COUNT));
        supervisors.add(s);
      }
      resultSet.close();
    }
  } finally {
    statement.close();
  }

  int count = supervisors.size();
  ISupervisor[] result = new ISupervisor[count];
  for (int i=0; i<count; i++)
    result[i] = (ISupervisor)supervisors.get(i);
  return result;
}

来自http://docs.oracle.com/javase/1.4.2/docs/api/java/sql/ResultSetMetaData.html

 ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM TABLE2");
 ResultSetMetaData rsmd = rs.getMetaData();
 int numberOfColumns = rsmd.getColumnCount();

ResultSet 包含给出行数的元数据。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM