web-dev-qa-db-ja.com

結果セットに1つ以上の行があるかどうかを確認するにはどうすればよいですか?

JDBCで結果セットに1行以上あるかどうかを確認するにはどうすればよいですか?

23
TopCoder
_ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1");
boolean isMoreThanOneRow = rs.first() && rs.next();
_

あなたはこれを尋ねませんでしたが、あなたはそれを必要とするかもしれません:

_boolean isEmpty = ! rs.first();
_

FORループの代わりに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(*)を使用して別のクエリを実行してレコード数を取得できますが、2つのクエリの実行にかかる時間の間に行を追加または削除できるため、数は概算にすぎないことに注意してください。

ResultSet概要からのサンプル

29
Marcus Adams

多くのオプションがあり、より多くのコンテキストを提供しないため、残っているのは推測することだけです。私の回答は、複雑さとパフォーマンスの昇順で並べ替えられています。

  1. select count(1) FROM ...を実行して答えを取得するだけです。実際にデータを選択して返す別のクエリを実行する必要があります。
  2. rs.next()で繰り返し、満足するまで数えます。それでも実際のデータが必要な場合は、同じクエリを再実行してください。
  3. ドライバーが逆方向反復をサポートしている場合は、rs.next()を数回実行してから、rs.previous()で巻き戻します。
1
mindas

これには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;
}
_
1
BalusC

簡単な提案:最初の結果行をフェッチしてから、次の結果行をフェッチしてみます。試行が成功した場合は、複数の行があります。

複数の行があり、そのデータを処理する場合は、最初の行からデータをキャッシュするか、スクロール可能な結果セットを使用して、結果を調べる前に先頭に戻ることができるようにする必要があります。

残りのクエリでSELECT COUNT(*)を実行して、SQLに直接この情報を要求することもできます。残りのクエリが返す行数に応じて、結果は0、1、またはそれ以上になります。これは非常に簡単に実装できますが、次に実際のクエリを読み取って処理する場合を想定して、DBへの2つのクエリが必要です。

0
Carl Smotricz

この実装では、いくつかの行を複製する代わりに、クエリの結果が空かどうかを確認できます。

ResultSet result = stmt.executeQuery("SELECT * FROM Table");

if(result.next()) {
   // Duplicate the code which should be pasted inside while
   System.out.println(result.getInt(1));
   System.out.println(result.getString(2));

   while(result.next()){
   System.out.println(result.getInt(1));
   System.out.println(result.getString(2));
   }
}else{
System.out.println("Query result is empty");
}

欠点:

  1. この実装では、コードの一部が複製されます。
  2. 結果に行がいくつあるかはわかりません。
0

exactlyが1行あることを確認する場合は、最初の行が最後であることを確認できます。

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.    
    // .. 
}
0
Garfield