Получить количество строк, возвращаемых ResultSet в Java

Я использовал 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? Или я должен написать свой собственный?


person Kiran    schedule 28.11.2011    source источник
comment
Дубликат: stackoverflow.com/ вопросы/7545820/   -  person james.garriss    schedule 31.08.2013


Ответы (13)


Вы можете использовать цикл 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");
}
person Jesper    schedule 28.11.2011
comment
я использую приведенный выше код, но и отображаю записи, но он теряет первую запись - person Karan; 04.07.2015
comment
индекс строки начинается с 1 в наборе результатов - person Francisc; 02.02.2016
comment
@FranciscI.B В приведенных выше примерах не используется индекс строки, поэтому не имеет значения, начинается ли индекс строки с 1 или с чего-либо еще. - person Jesper; 04.02.2016
comment
Может быть, @KaranRajput использует его. Я не знаю, как можно потерять первую запись, так что это был совет на случай, если он использует необработанный индекс. - person Francisc; 05.02.2016

Во-первых, вы должны создать 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.

person Tu Tran    schedule 28.11.2011
comment
будьте осторожны: в случае ojdbc, если вы вызываете rs.last, набор результатов повторяется и кэшируется. так что это может привести к неожиданному потреблению памяти - person Vasilii Ruzov; 06.05.2019

Простой метод 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, и использование этого метода вызовет исключение.

person mprabhat    schedule 28.11.2011
comment
РезультатSet.last(); строка возвращает логическое значение, пожалуйста, поставьте оператор if. - person Nael Marwan; 22.05.2017

Другой способ различить 0 строк или несколько строк из ResultSet:

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 ;    
}
person Fathah Rehman P    schedule 26.06.2012

Метод res.next() перенесет указатель на следующую строку. и в вашем коде вы используете его дважды, сначала для условия if (курсор перемещается в первую строку), затем для условия while (курсор перемещается во вторую строку).

Поэтому, когда вы получаете доступ к своим результатам, они начинаются со второй строки. Таким образом, в результатах отображается на одну строку меньше.

вы можете попробовать это:

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

Вы можете посчитать с помощью 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 для подсчета на основе критериев.

person Emmanuel John    schedule 13.08.2015
comment
красивое и простое решение!! - person im_bhatman; 11.07.2018

Вы можете подумать, что JDBC — это богатый API, а ResultSet имеет так много методов, тогда почему бы не использовать только метод getCount()? Ну, для многих баз данных, например. Oracle, MySQL и SQL Server, ResultSet — это потоковый API, это означает, что он не загружает (или даже не извлекает) все строки с сервера базы данных. Повторяя до конца ResultSet, вы можете значительно увеличить время, необходимое для выполнения в определенных случаях.

Кстати, если вам нужно, есть несколько способов сделать это, например. используя методы ResultSet.last() и ResultSet.getRow(), это не лучший способ сделать это, но он работает, если вам это абсолютно необходимо.

Однако в Java легко получить количество столбцов из ResultSet. API JDBC предоставляет класс ResultSetMetaData, который содержит методы для возврата количества столбцов, возвращаемых запросом, и удерживаемых ResultSet.

person Cassia    schedule 20.11.2019
comment
когда в последней части вы ссылаетесь на то, что JDBC API предоставляет класс ResultSetMetaData, который содержит методы для возврата количества столбцов, возвращаемых запросом, и удержания с помощью resultSet, вы на самом деле имеете в виду количество строк через класс ResultSetMetaData? В противном случае это не имеет отношения к вопросу как таковому и просто добавляет путаницы. - person George Xavier; 07.01.2020

Вы можете загрузить ResultSet в TableModel, затем создать JTable, который использует эту TableModel, а затем использовать метод table.getRowCount(). Если вы собираетесь отображать результат запроса, вы все равно должны это сделать.

ResultSet resultSet;
resultSet = doQuery(something, somethingelse);
KiransTableModel myTableModel = new KiransTableModel(resultSet);
JTable table = new JTable(KiransTableModel);
int rowCount;
rowCount = table.getRowCount;
person bsdarby    schedule 04.09.2014

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 перемещает курсор до первой строки, поэтому возвращаемое отрицательное значение указывает на отсутствие записей в БД.

person pradeep kumar    schedule 30.07.2016
comment
Можете ли вы уточнить с объяснением, как это может помочь? - person kommradHomer; 31.07.2016
comment
Первая строка кода @kommradHomer говорит, что мы можем перемещаться в любое место в наборе результатов (либо в первую строку, либо в последнюю строку, либо перед первой строкой без необходимости проходить строку за строкой, начиная с первой строки, что занимает много времени). вторая строка кода извлекается записи, соответствующие запросу здесь, я предполагаю (25 записей), третья строка кода перемещает курсор в последнюю строку, а последняя строка кода получает текущий номер строки, который в моем случае равен 25. если записей нет, rs.last возвращает 0, а getrow перемещает курсор до первой строки, поэтому возвращаемое отрицательное значение указывает на отсутствие записей в БД. - person pradeep kumar; 05.08.2016

это мое решение

 ResultSet rs=Statement.executeQuery("query");

    int rowCount=0;


    if (!rs.isBeforeFirst()) 
      {

           System.out.println("No DATA" );
        } else {
            while (rs.next()) {
                rowCount++; 
            System.out.println("data1,data2,data3...etc..");
            }
            System.out.println(rowCount);
            rowCount=0;
            rs.close();
            Statement.close();
      }
person Yusuf Kalsen    schedule 24.01.2017

Если ваш запрос похож на этот SELECT Count(*) FROM tranbook, сделайте это rs.next(); System.out.println(rs.getInt("Count(*)"));

person Rkmr039    schedule 21.08.2019

В моем случае мне нужно было получить общее количество строк из ResultSet, а также получить доступ к значениям ResultSet, если общее количество строк не достигло предела файла XLS.

Для этого мне пришлось внести две коррективы в мой код:

1) Изменение конструкции объекта PreparedStatement

Объект ResultSet по умолчанию имеет курсор, который перемещается только вперед. Таким образом, вы можете перебрать его только один раз и только от первой строки до последней строки. Можно создавать объекты ResultSet, которые можно прокручивать. Следующий фрагмент кода иллюстрирует, как сделать результирующий набор с возможностью прокрутки и нечувствительным к обновлениям другими.

PreparedStatement ps = connection.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, 
ResultSet.CONCUR_READ_ONLY);

2) Получить общее количество строк. Следующий фрагмент кода иллюстрирует, как:

ResultSet rs = ps.executeQuery();
rs.last();
int totalRowsResult = rs.getRow();

PS: Если количество записей результата запроса слишком велико, вы можете исчерпать память на сервере Java, получив исключение: java.lang.OutOfMemoryError: пространство кучи Java. Это исключение возникнет при выполнении метода rs.last()

3) Снова получите доступ к ResultSet, и вы не получите сообщение: набор результатов исчерпан. Итак, вам нужно сбросить набор результатов наверх, используя rs.first() или rs.absolute(1). Следующий фрагмент кода иллюстрирует, как:

rs.first();
System.out.println(rs.getString(1));
person Beatriz Wilges    schedule 05.03.2020

Вы можете использовать res.previous() следующим образом:

ResulerSet res = getDate();
if(!res.next()) {
    System.out.println("No Data Found.");
} else {
    res.previous();
    while(res.next()) {
      //code to display the data in the table.
    }
}
person Yatin    schedule 17.06.2014