2010-04-07 2 views
21

Как проверить, имеет ли набор результатов один ряд или более с JDBC?Как проверить, имеет ли набор результатов один ряд или более?

+0

Это действительно то, чего не хватает в JDBC, причина в том, что не все системы базы данных поддерживают rt получать размер результирующего набора заранее (потому что результаты не предваряются). К сожалению, это означает, что вы не можете легко использовать эти функции в базах данных, которые его поддерживают, например MySQL. – Thirler

+0

Возможный дубликат [Java ResultSet, как проверить, есть ли какие-либо результаты] (http://stackoverflow.com/questions/867194/java-resultset-how-to-check-if-there-are-any-results) – rogerdpack

ответ

28
ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1"); 
boolean isMoreThanOneRow = rs.first() && rs.next(); 

Вы не спрашивали это одно, но оно может понадобиться:

boolean isEmpty = ! rs.first(); 

Как правило, нам не нужно количество строк, потому что мы используем цикл WHILE для перебора результирующего набора а для цикла:

ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1"); 
while (rs.next()) { 
    // retrieve and print the values for the current row 
    int i = rs.getInt("a"); 
    String s = rs.getString("b"); 
    float f = rs.getFloat("c"); 
    System.out.println("ROW = " + i + " " + s + " " + f); 
} 

Однако, в некоторых случаях может потребоваться окно результатов, и вы должны рассчитывать раньше времени записи для отображения пользователю что-то вроде Row 1 to 10 of 100. Вы можете сделать отдельный запрос с SELECT COUNT(*), чтобы получить счетчик записей, но обратите внимание, что счетчик является приблизительным, так как строки могут быть добавлены или удалены между временем, которое требуется для выполнения двух запросов.

Пример из ResultSet Overview

+0

isMoreThanOneRow сообщит мне об ошибке. Запрошенная операция не поддерживается только для прямых наборов результатов. –

+0

@ Vodo-SioskBaas, вам нужно сделать это сразу после инструкции 'executeQuery', так что' first() 'не нужно перематывать или менять курсор так, чтобы он мог перемотать назад. –

0

Мое предложение: выберите первую строку результатов, а затем попробуйте выбрать следующий. Если попытка выполнена успешно, у вас есть несколько строк.

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

Вы также можете запросить SQL непосредственно для этой информации, выполнив SELECT COUNT(*) в остальной части вашего запроса; результат будет равен 0, 1 или более, в зависимости от того, сколько строк будет возвращено остальной частью запроса. Это довольно просто реализовать, но включает два запроса в БД, предполагая, что вы захотите прочитать и обработать фактический запрос.

1

Есть много вариантов, и так как вы не обеспечивают больше контекста единственное, что осталось угадать. Мои ответы сортируются по сложности и производительности по возрастанию.

  1. Просто запустите select count(1) FROM ... и получите ответ. Вам нужно будет запустить другой запрос, который фактически выбирает и возвращает данные.
  2. Итерации с rs.next() и считайте, пока вы не будете счастливы. Затем, если вам все еще нужны фактические данные, повторно запустите тот же запрос.
  3. Если ваш драйвер поддерживает обратную итерацию, перейдите на rs.next() пару раз, а затем перемотайте назад с помощью rs.previous().
+2

Если ваш драйвер не поддерживает обратную итерацию, 'first()' обычно работает для начала. –

1

Для этого вам не нужен JDBC. Нормальная идиома - собирать все результаты в коллекции и использовать методы сбора, такие как List#size().

List<Item> items = itemDAO.list(); 

if (items.isEmpty()) { 
    // It is empty! 
if (items.size() == 1) { 
    // It has only one row! 
} else { 
    // It has more than one row! 
} 

где list() метод выглядеть как-то:

public List<Item> list() throws SQLException { 
    Connection connection = null; 
    Statement statement = null; 
    ResultSet resultSet = null; 
    List<Item> items = new ArrayList<Item>(); 

    try { 
     connection = database.getConnection(); 
     statement = connection.createStatement(); 
     resultSet = statement.executeQuery(SQL_LIST); 
     while (resultSet.next()) { 
      Item item = new Item(); 
      item.setId(resultSet.getLong("id")); 
      item.setName(resultSet.getString("name")); 
      // ... 
      items.add(item); 
     } 
    } finally { 
     if (resultSet != null) try { resultSet.close(); } catch (SQLException logOrIgnore) {} 
     if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {} 
     if (connection != null) try { connection.close(); } catch (SQLException logOrIgnore) {} 
    } 

    return items; 
} 
+0

Это не очень хорошо масштабируется. Что делать, если набор результатов имеет миллионы строк? – mindas

+0

@mindas: Тогда уже не было смысла «ВЫБРАТЬ * ОТ таблицы». Вам нужно «SELECT COUNT (*) FROM table». JDBC - это просто не правильный инструмент для этой конкретной цели, и именно по этой причине в JDBC не существует фиктивного метода 'ResultSet # size()'. – BalusC

+0

Оригинальный вопрос никогда не говорил, что он делает 'SELECT * FROM table' и я не предлагал этого. У исходного вопроса нет предположения, что все данные действительно необходимы. – mindas

-4

Получить количество строк, используя ResultSetMetaData класс.

Из кода и может создать ResultSetMetaData как:

ResultSetMetaData rsmd = resultSet.getMetaData(); //get ResultSetMetaData 
rsmd.getColumnCount();  // get row count from resultsetmetadata 
+0

-1 ResultSetMetaData не имеет ничего общего с количеством строк. Rsmd.getColumnCount() дает вам количество столбцов вашего результирующего набора. – bluish

-1
public int rowCountValue(ResultSet rsValue) throws SQLException { 
    ResultSet rowCountValue = rsValue; 
    int countRow = 0; 
    while (rowCountValue.next()) { 
     countRow++; 
    } 
    return countRow; 
} 
+0

. Почему это происходит при голосовании, сообщите об этом, так как код работает –

0

Если вы хотите, чтобы убедиться, что есть точно один ряд, вы можете гарантировать, что первая строка является последней :

ResultSet rs = stmt.executeQuery("SELECT a FROM Table1 WHERE b=10"); 
if (rs.isBeforeFirst() && rs.next() && rs.isFirst() && rs.isLast()) { 
    // Logic for where there's exactly 1 row 
    Long valA = rs.getLong("a");  
    // ... 
} 
else { 
    // More that one row or 0 rows returned.  
    // .. 
} 
Смежные вопросы