在Java中获取ResultSet返回的行数

77

我使用了一个返回固定行数的ResultSet。我的代码大概是这样的:

ResultSet res = getData();
if(!res.next())
{
    System.out.println("No Data Found");
}
while(res.next())
{
    // code to display the data in the table.
}

有没有方法可以检查ResultSet返回的行数?还是我必须自己写?


请返回已翻译的文本:重复的问题:https://dev59.com/pWsz5IYBdhLWcg3w9ssQ - james.garriss
14个回答

78

首先,您应该创建可以通过命令移动光标的Statement

Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);

接下来按照以下方式检索ResultSet:

ResultSet rs = stmt.executeQuery(...);

将光标移动到最新的行并获取该行:

if (rs.last()) {
    int rows = rs.getRow();
    // Move to beginning
    rs.beforeFirst();
    ...
}

那么rows变量将包含SQL返回的行数。


2
注意:在使用ojdbc时,如果调用rs.last,则结果集会被迭代和缓存。这可能会导致意外的内存消耗。 - Vasilii Ruzov

67

你可以使用do ... while循环代替while循环,这样rs.next()将在循环执行后调用,代码如下:

if (!rs.next()) {                            //if rs.next() returns false
                                             //then there are no rows.
    System.out.println("No records found");

}
else {
    do {
        // Get data from the current row and use it
    } while (rs.next());
}

或者在获取行时自己计算行数:

int count = 0;

while (rs.next()) {
    ++count;
    // Get data from the current row and use it
}

if (count == 0) {
    System.out.println("No records found");
}

我正在使用以上的代码并显示记录,但它丢失了第一条记录。 - Karan
2
结果集中的行索引从1开始。 - Francisc
@FranciscI.B 上面的示例中没有使用行索引,因此行索引从1或其他任何数字开始都无所谓。 - Jesper
也许@KaranRajput正在使用它。我不知道如何丢失第一条记录,所以这是一个提示,以防他正在使用原始索引。 - Francisc

31

一个简单的getRowCount方法可以如下所示:

private int getRowCount(ResultSet resultSet) {
    if (resultSet == null) {
        return 0;
    }

    try {
        resultSet.last();
        return resultSet.getRow();
    } catch (SQLException exp) {
        exp.printStackTrace();
    } finally {
        try {
            resultSet.beforeFirst();
        } catch (SQLException exp) {
            exp.printStackTrace();
        }
    }

    return 0;
}

请注意,此方法需要一个可滚动的resultSet,因此在创建连接时你必须指定滚动选项。默认值为FORWARD,如果使用此方法将会抛出异常。


2
resultSet.last()方法返回布尔值,请使用if语句进行判断。 - Nael Marwan

8

ResultSet中区分0行和有数据的另一种方法:

ResultSet res = getData();

if(!res.isBeforeFirst()){          //res.isBeforeFirst() is true if the cursor
                                   //is before the first row.  If res contains
                                   //no rows, rs.isBeforeFirst() is false.

    System.out.println("0 rows");
}
else{
    while(res.next()){
        // code to display the rows in the table.
    }
}

如果您需要在ResultSet中知道行数,这里有一个获取方法:

public int getRows(ResultSet res){
    int totalRows = 0;
    try {
        res.last();
        totalRows = res.getRow();
        res.beforeFirst();
    } 
    catch(Exception ex)  {
        return 0;
    }
    return totalRows ;    
}

6

res.next() 方法会将指针移动到下一行。在你的代码中,你使用了两次该方法,首先用于 if 条件(光标移动到第一行),然后用于 while 条件(光标移动到第二行)。

所以当你访问结果时,它从第二行开始。因此在结果中显示少一行。

你可以尝试这样做:

if(!res.next()){ 
    System.out.println("No Data Found");  
}
else{
    do{
       //your code
    } 
    while(res.next());
}

3
        rs.last();
        int rows = rs.getRow();
        rs.beforeFirst();

1
你可能认为JDBC是一个丰富的API,并且ResultSet有很多方法,那为什么不只提供一个getCount()方法呢?对于许多数据库,例如Oracle、MySQL和SQL Server,ResultSet是一个流式API,这意味着它不会加载(或者甚至获取)来自数据库服务器的所有行。迭代到ResultSet的末尾可能会在某些情况下显著增加执行时间。

顺便说一句,如果你非要这样做,有几种方法可以实现,例如使用ResultSet.last()和ResultSet.getRow()方法,但这并不是最好的方法,只有在绝对需要时才能使用。

尽管如此,在Java中从ResultSet获取列数很容易。JDBC API提供了一个ResultSetMetaData类,其中包含返回查询返回的列数并由ResultSet保存的方法。

1
当你在最后一部分提到“JDBC API提供了一个ResultSetMetaData类,其中包含返回查询返回的列数并由resultSet保持的方法”时,你实际上是指通过ResultSetMetaData类返回行数吗?否则,这与问题本身无关,只会增加更多的混淆。 - George Xavier

1

您可以使用SQL进行计数并从结果集中检索答案,方法如下:

Statment stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, 
                                     ResultSet.CONCUR_READ_ONLY);
ResultSet ct = stmt.executeQuery("SELECT COUNT(*) FROM [table_name]");
if(ct.next()){
   td.setTotalNumRows(ct.getInt(1));
}

在这里我正在计算除了你以外的所有内容,但是您可以轻松修改SQL语句,根据条件进行计数。


1
简单而巧妙的解决方案!! - im_bhatman

0
如果您的查询类似于这样:SELECT Count(*) FROM tranbook,那么请执行以下操作:rs.next(); System.out.println(rs.getInt("Count(*)"));

0
Statement st = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
ResultSet rs=st.executeQuery("select * from emp where deptno=31");
rs.last();
System.out.println("NoOfRows: "+rs.getRow());

第一行代码表示我们可以在结果集中任意移动(无需从第一行开始逐行遍历),包括移到第一行、最后一行或第一行之前。这样做可以节省时间。第二行代码获取与查询匹配的记录,我在这里假设有25条记录。第三行代码将光标移动到最后一行,最后一行代码获取当前行号,在我的情况下是25。如果没有记录,则rs.last返回0,并且getrow将光标移动到第一行之前,因此返回负值表示数据库中没有记录。


你能详细解释一下这可能如何有所帮助吗? - kommradHomer
@kommradHomer 第一行代码表示我们可以在结果集中任意移动(无需从第一行开始逐行遍历),包括移到第一行、最后一行或者第一行之前,这样可以节省时间。第二行代码获取与查询匹配的记录,这里我假设有25条记录。第三行代码将光标移动到最后一行,最后一行代码获取当前行号,在我的例子中是25。如果没有记录,rs.last返回0并将光标移动到第一行之前,因此返回负值表示数据库中没有记录。 - pradeep kumar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接