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

时间:2011-10-25 08:16:11

标签: java jdbc resultset

我正在尝试创建一个简单的方法,它接收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.

提前感谢指针!

13 个答案:

答案 0 :(得分:56)

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

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 ...

答案 1 :(得分:33)

你的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;

获取行数

答案 2 :(得分:20)

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'使用此解决方案

Sqlite在JDBC中不支持。

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

那时候使用这个解决方案。

谢谢..

答案 3 :(得分:7)

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

答案 4 :(得分:5)

我刚做了一个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;
}

答案 5 :(得分:3)

如果你有表并将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", "");
  }
}

答案 6 :(得分:2)

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

答案 7 :(得分:2)

大多数驱动程序仅支持转发结果集 - 因此不支持像last,beforeFirst等方法。

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

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

答案 8 :(得分:2)

其他人已经回答了如何解决你的问题,所以我不会重复已经说过的话,但我会说:你应该想办法解决你的问题而不知道结果集的数量在阅读结果之前。

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

现在我当然不是说在读取结果集之前从未出现过需要行计数的情况。我只是说,在大多数情况下,当人们认为在阅读之前他们需要结果集计数时,他们可能不会,并且值得花5分钟考虑是否有另一种方式。

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

答案 9 :(得分:1)

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

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

if( rs.next() ){

   Do nothing
} else {
  No records fetched!
}

请参阅here

答案 10 :(得分:0)

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

请注意,Supervisor类在这里实现了ISupervisor接口,但在Java中你无法从object [](ArrayList的plain 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;
}

答案 11 :(得分:0)

以下两个选项适用于我:

1)返回ResultSet中行数的函数。

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语句。

答案 12 :(得分:-7)

来自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包含提供行数的元数据。