Java ResultSet, wie überprüft wird, ob Ergebnisse vorliegen


311

Die Ergebnismenge hat keine Methode für hasNext. Ich möchte überprüfen, ob das resultSet einen Wert hat

Ist das der richtige Weg?

if (!resultSet.next() ) {
    System.out.println("no data");
} 

2
Für zukünftige Leser wie mich: Antworten, die mir geholfen haben, sind die von Felype und Dermot Doherty
Benj

Antworten:


237

Das ist richtig, anfangs zeigt der ResultSetCursor vor der ersten Zeile auf. Wenn der erste Aufruf next()zurückkehrt, falsewaren keine Daten in der ResultSet.

Wenn Sie diese Methode verwenden, müssen Sie möglicherweise beforeFirst()sofort danach aufrufen , um sie zurückzusetzen, da sie sich jetzt hinter der ersten Zeile positioniert hat.

Es sollte jedoch beachtet werden, dass Seifers Antwort unten eine elegantere Lösung für diese Frage ist.


37
Aber denken Sie daran, wenn es / sind / Zeilen gibt, zeigen Sie nach diesem Test auf die erste Zeile. Stellen Sie also sicher, dass Sie nicht versehentlich eine Zeile überspringen.
Matthew Flaschen

1
Guter Punkt, dass der Cursor (Zeiger) auf die erste Zeile zeigt
JohnMerlino

@MatthewFlaschen, Sie haben Recht, um das Problem des Überspringens der ersten Zeile zu lösen, habe ich ein do {...} while (rs.next) verwendet;
Israelm

8
Sie können auch einfach aufrufen isBeforeFirst(), um zu testen, ob Zeilen zurückgegeben werden, ohne den Cursor zu bewegen, und dann normal fortfahren.
SnakeDoc

528

Angenommen, Sie arbeiten mit einem neu zurückgegebenen ResultSetBenutzer, dessen Cursor vor der ersten Zeile zeigt, können Sie dies einfacher überprüfen, indem Sie einfach aufrufen isBeforeFirst(). Dies vermeidet das Zurückverfolgen, wenn die Daten gelesen werden sollen.

Wie in der Dokumentation erläutert , gibt dies false zurück, wenn sich der Cursor nicht vor dem ersten Datensatz befindet oder wenn das ResultSet keine Zeilen enthält .

if (!resultSet.isBeforeFirst() ) {    
    System.out.println("No data"); 
} 

 


15
Danke, ja, ich weiß, aber ich bin auf das gleiche Problem gestoßen und war nicht zufrieden mit dem Blick, vorwärts zu gehen, um zu überprüfen, dann rückwärts, um zu lesen. Ich dachte, diese einfachere Lösung würde auch anderen zugute kommen, die sich in derselben Situation befinden.
Seifer

5
Beachten Sie, dass die Ergebnismenge zumindest für DB2 vom Typ "scrollbar" sein muss. Dies kann festgelegt werden, wenn Sie die auszuführende Anweisung erstellen.
Laurence Dougal Myers

1
Felypes Antwort unten ist vollständiger
Tom Howard

Aus der Oracle-Dokumentation: Hinweis: Die Unterstützung der isBeforeFirst-Methode ist optional für ResultSets mit dem Ergebnismengen-Typ TYPE_FORWARD_ONLY
emi-le

52

Sie könnten immer die nächste im Voraus machen und einfach eine Post-Loop-Prüfung durchführen

if (!resultSet.next() ) {
    System.out.println("no data");
} else {

    do {
     //statement(s)
    } while (resultSet.next());
}

21

Normalerweise würden Sie so etwas tun:

while ( resultSet.next() ) { 
   // Read the next item
   resultSet.getString("columnName");
}

Wenn Sie einen leeren Satz melden möchten, fügen Sie eine Variable hinzu, die die gelesenen Elemente zählt. Wenn Sie nur einen einzelnen Artikel lesen müssen, ist Ihr Code ausreichend.


16

Um ganz sicher zu sein, dass die Ergebnismenge unabhängig von der Cursorposition leer ist oder nicht, würde ich Folgendes tun:

public static boolean isMyResultSetEmpty(ResultSet rs) throws SQLException {
    return (!rs.isBeforeFirst() && rs.getRow() == 0);
}

Diese Funktion gibt true zurück, wenn ResultSet leer ist, false, wenn nicht, oder löst eine SQLException aus, wenn das ResultSet geschlossen / nicht initialisiert ist.


12

Verwenden Sie hierfür am besten ResultSet.next () zusammen mit der Syntax do {...} while ().

Der Aufruf "Nach Ergebnissen suchen" beim Aufrufen von ResultSet.next () bewegt den Cursor in die erste Zeile. Verwenden Sie daher die Syntax do {...} while (), um diese Zeile zu verarbeiten, während Sie die verbleibenden von der Schleife zurückgegebenen Zeilen weiter verarbeiten.

Auf diese Weise können Sie nach Ergebnissen suchen und gleichzeitig alle zurückgegebenen Ergebnisse verarbeiten.

if(resultSet.next()) { // Checks for any results and moves cursor to first row,
    do { // Use 'do...while' to process the first row, while continuing to process remaining rows

    } while (resultSet.next());
}

8

Nach der brauchbarsten Antwort wird vorgeschlagen, "isBeforeFirst ()" zu verwenden. Dies ist nicht die beste Lösung, wenn Sie keinen "Nur-Weiterleitungstyp" haben .

Es gibt eine Methode namens " .first () ". Es ist weniger übertrieben, genau das gleiche Ergebnis zu erzielen. Sie überprüfen, ob sich etwas in Ihrer "Ergebnismenge" befindet, und bewegen den Cursor nicht weiter.

In der Dokumentation heißt es: "(...) false, wenn die Ergebnismenge keine Zeilen enthält ".

if(rs.first()){
    //do stuff      
}

Sie können auch einfach isBeforeFirst () aufrufen, um zu testen, ob Zeilen zurückgegeben werden, ohne den Cursor zu bewegen, und dann normal fortfahren. - SnakeDoc 2. September 14 um 19:00 Uhr

Es gibt jedoch einen Unterschied zwischen "isBeforeFirst ()" und "first ()". Erzeugt zuerst eine Ausnahme, wenn dies für eine Ergebnismenge vom Typ "Nur weiterleiten" erfolgt.

Vergleichen Sie die beiden Wurfabschnitte: http://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html#isBeforeFirst () http://docs.oracle.com/javase/7/docs /api/java/sql/ResultSet.html#first ()

Okay, im Grunde bedeutet dies, dass Sie "isBeforeFirst" verwenden sollten, solange Sie einen "nur vorwärts" -Typ haben. Ansonsten ist es weniger übertrieben, "first ()" zu verwenden.


1
Wie ist es "weniger übertrieben", genau das gleiche Ergebnis zu erzielen? Es scheint mir, dass der Zweck von first () darin besteht, den Cursor in die erste Zeile zu bewegen, wenn er noch nicht vorhanden ist (und true zurückzugeben, wenn dies erfolgreich war). isBeforeFirst ist nur eine rein diagnostische Funktion und scheint eher für die Zwecke des Autors geeignet zu sein. Außerdem gibt die Art und Weise, wie first () formuliert ist, true zurück, solange es sich "in einer gültigen Zeile" befindet ... was seltsam ist, da man denken würde, dass es als "in der ersten Zeile" formuliert wird. Für mich sehe ich in diesem Szenario keinen Vorteil der Verwendung von first (), es sei denn, Ihr Cursor ist vorgerückt und Sie möchten ihn wieder an den Anfang bringen.
Jon

5

Das würde funktionieren, wenn Sie sehen möchten, ob die Ergebnismenge Zeilen enthält. Ja.

Beachten Sie, dass next()immer in die nächste Zeile gewechselt wird. Wenn Sie also vorhaben, aus der Ergebnismenge zu lesen, müssen Sie dies berücksichtigen.

Die übliche Verwendung mit ResultSet (beim einfachen Lesen) ist:

while (resultSet.next())
{
   ... read from the row here ...
}

Was offensichtlich nicht richtig funktioniert, wenn Sie next()bereits einmal aufgerufen haben , um zu überprüfen, ob die Ergebnismenge leer war. Achten Sie also darauf. Obwohl es Methoden zum "Sichern" gibt, werden sie nicht für alle Arten von Ergebnismengen unterstützt.


5

Dies ist ein praktisches und leicht zu lesendes Stück, glaube ich.

        if (res.next()) {
            do {

                // successfully in. do the right things.

            } while (res.next());
        } else {
           // no results back. warn the user.
        }

2
if (!resultSet.isAfterLast() ) {    
System.out.println("No data"); 
} 

isAfterLast() gibt auch false für leere Ergebnismenge zurück, aber da sich der Cursor sowieso vor der ersten Zeile befindet, scheint diese Methode klarer zu sein.


2
if(resultSet.first) {

} else { 
    system.out.println("No raw or resultSet is empty");
}

Denn wenn ResultSet kein Raw hat, wird resultSet.firstfalse zurückgegeben.


Aber es bewegt den Cursor unnötig in die erste Zeile, und es kann die weitere Verwendung des Objekts "zurücksetzen" verwirren und Daten verlieren
Tigran Babajanyan

Obwohl dies besser aussieht, funktioniert es nicht mit einer Cursor-Ergebnismenge, die nur vorwärts geht.
Eliteproxy

1

Am besten überprüfen Sie die erste Zeile, damit Sie den Fehler beim Überspringen einer Zeile vermeiden können, wenn Sie die Daten abrufen möchten. So etwas wie: if (! ResultSet.first ()) {System.out.println ("keine Daten"); }}


1

Mit resultSet.next () können Sie das Ergebnis leicht abrufen, unabhängig davon, ob resultSet einen beliebigen Wert enthält oder nicht

ResultSet resultSet = preparedStatement.executeQuery();
if(resultSet.next())
 //resultSet contain some values
else
 // empty resultSet

Wiederholen Sie vorhandene Antworten nicht.
James.garriss

1
ResultSet result = stmt.executeQuery(sqlQuery);
if (!result.next())
    status = "ERROR";
else
    status = "SUCCESS";

1

Ich habe versucht, die aktuelle Zeile auf den ersten Index zu setzen (mit Primärschlüsseln). ich würde vorschlagen

if(rs.absolute(1)){
    System.out.println("We have data");
} else {
    System.out.println("No data");
}

Wenn das ResultSet ausgefüllt ist, zeigt es vor der ersten Zeile. Wenn Sie es auf die erste Zeile setzen (angezeigt durch rs.absolute(1)), wird true zurückgegeben, was bedeutet, dass es erfolgreich in Zeile 1 platziert wurde, oder false, wenn die Zeile nicht vorhanden ist. Wir können dies auf extrapolieren

for(int i=1; rs.absolute(i); i++){
    //Code
}

Dies setzt die aktuelle Zeile auf Position i und schlägt fehl, wenn die Zeile nicht vorhanden ist. Dies ist nur eine alternative Methode zu

while(rs.next()){
    //Code
}

Wie ist deine Antwort?
CMedina

1

Ich habe die folgende Methode erstellt, um zu überprüfen, ob ein ResultSet leer ist.

public static boolean resultSetIsEmpty(ResultSet rs){        
    try {
        // We point the last row
        rs.last();
        int rsRows=rs.getRow(); // get last row number

        if (rsRows == 0) {
            return true;
        }

        // It is necessary to back to top the pointer, so we can see all rows in our ResultSet object.
        rs.beforeFirst();
        return false;
    }catch(SQLException ex){            
        return true;
    }
}

Es ist sehr wichtig, die folgenden Überlegungen zu berücksichtigen:

Das CallableStatement- Objekt muss so eingestellt werden, dass das ResultSet-Objekt am Ende und wieder oben angezeigt wird.

TYPE_SCROLL_SENSITIVE : Das ResultSet-Objekt kann am Ende verschoben und wieder nach oben verschoben werden. Weitere können letzte Änderungen abfangen.

CONCUR_READ_ONLY : Wir können die ResultSet-Objektdaten lesen, aber nicht aktualisieren.

CallableStatement proc = dbconex.prepareCall(select, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);

1

Ich denke, der einfachste Weg, die Ergebnismenge zu überprüfen, ist über CollectionUtils unter dem Paket org.apache.commons.collections.CollectionUtils

if(CollectionUtils.isNotEmpty(resultList)){
  /**
  * do some stuff
  */
}

Dadurch wird sowohl nach null als auch nach leeren Ergebnismengen gesucht.

Weitere Informationen finden Sie im folgenden Dokument. CollectionUtils


1
ResultSet ist keine Sammlung.
Joachim Lous

1

Warum nicht rs.getRow () verwenden?

int getRow()
           throws SQLException
Retrieves the current row number. The first row is number 1, the second number 2, and so on.
Note:Support for the getRow method is optional for ResultSets with a result set type of TYPE_FORWARD_ONLY

Returns:
the current row number; 0 if there is no current row
Throws:
SQLException - if a database access error occurs or this method is called on a closed result set
SQLFeatureNotSupportedException - if the JDBC driver does not support this method
Since:
1.2

Für mich scheint "if (rs.getRow ()! = 0)" gut zu funktionieren.


0

Sie können so etwas tun

boolean found = false;

while ( resultSet.next() )
{
    found = true;
    resultSet.getString("column_name");
}

if (!found)
    System.out.println("No Data");

1
WAAAY zu kompliziert.
Jordaniac89

0
ResultSet rs = rs.executeQuery();
if(rs.next())
{
  rs = rs.executeQuery();
  while(rs.next())
  {
    //do code part
  }
}
else
{
  //else if no result set
}

Es ist besser, die Abfrage erneut auszuführen, da beim Aufruf der if(rs.next()){....}ersten Zeile von ResultSet die Ausführung ausgeführt wird und danach while(rs.next()){....}das Ergebnis aus der nächsten Zeile angezeigt wird . Daher denke ich, dass die erneute Ausführung der Abfrage im Inneren ifdie bessere Option ist.


5
-1 Dies ist keine bessere Option. Warum die Datenbank zweimal abfragen? Was ist, wenn sich die Daten zwischen den Anrufen drastisch ändern? Das ist verschwenderisch.
Toby Caulk

-2

Zu Beginn zeigt das Ergebnismengenobjekt (rs) auf die BFR (vor dem ersten Datensatz). Sobald wir rs.next () verwenden, zeigt der Cursor auf den ersten Datensatz und das rs hält "true". Mit der while-Schleife können Sie alle Datensätze der Tabelle drucken. Nachdem alle Datensätze abgerufen wurden, bewegt sich der Cursor auf ALR (Nach dem letzten Datensatz) und wird auf Null gesetzt. Nehmen wir an, dass die Tabelle zwei Datensätze enthält.

if(rs.next()==false){
    // there are no records found
    }    

while (rs.next()==true){
    // print all the records of the table
    }

Kurz gesagt, wir können die Bedingung auch als while (rs.next ()) schreiben.


3
Ihre while-Schleife hat keine Chance, die zurückgegebene erste Zeile zu bearbeiten, was bei diesem Ansatz ein ziemlich schwerwiegender Fehler zu sein scheint. Es gibt viele Vorschläge, die besser sind als dieser.
Jules
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.