Java ResultSet comment vérifier s'il y a des résultats

312

L'ensemble de résultats n'a pas de méthode pour hasNext. Je veux vérifier si le resultSet a une valeur

C'est la bonne route

if (!resultSet.next() ) {
    System.out.println("no data");
} 
Kal
la source
2
Pour les futurs lecteurs comme moi: les réponses qui m'ont aidé sont celles de Felype et Dermot Doherty
Benj

Réponses:

239

C'est vrai, au départ, le ResultSetcurseur pointe vers la première ligne, si le premier appel à next()renvoie falsealors il n'y avait pas de données dans le ResultSet.

Si vous utilisez cette méthode, vous devrez peut-être appeler beforeFirst()immédiatement après pour la réinitialiser, car elle s'est positionnée au-delà de la première ligne maintenant.

Il convient toutefois de noter que la réponse de Seifer ci-dessous est une solution plus élégante à cette question.

ninesided
la source
37
Mais gardez à l'esprit, s'il y a / sont / lignes, après ce test, vous pointerez vers la première ligne. Assurez-vous donc de ne pas sauter accidentellement une rangée.
Matthew Flaschen
1
Bon point que le curseur (pointeur) pointe vers la première ligne
JohnMerlino
@MatthewFlaschen, vous avez raison, pour résoudre le problème de sauter la première ligne, j'ai utilisé un do {...} while (rs.next);
Israelm
8
Vous pouvez également simplement appeler isBeforeFirst()pour tester s'il y a des lignes retournées sans faire avancer le curseur, puis procédez normalement.
SnakeDoc du
529

En supposant que vous travaillez avec un nouveau retour ResultSetdont le curseur pointe avant la première ligne, un moyen plus simple de vérifier ceci consiste à simplement appeler isBeforeFirst(). Cela évite d'avoir à revenir en arrière si les données doivent être lues.

Comme expliqué dans la documentation , cela renvoie false si le curseur n'est pas avant le premier enregistrement ou s'il n'y a pas de lignes dans le ResultSet .

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

 

Seifer
la source
15
Merci, oui, je sais, mais j'ai rencontré le même problème et je n'étais pas satisfait du look d'avancer pour vérifier puis de reculer pour lire. Je pensais que cette solution plus simple profiterait également à d'autres qui se trouvent dans la même situation.
Seifer
5
Notez qu'au moins pour DB2, le jeu de résultats doit être de type "scrollable". Cela peut être défini lorsque vous créez l'instruction à exécuter.
Laurence Dougal Myers
1
La réponse de Felype ci - dessous est plus complète
Tom Howard
Dans la documentation Oracle: Remarque: la prise en charge de la méthode isBeforeFirst est facultative pour les ensembles de résultats avec un type d'ensemble de résultats de TYPE_FORWARD_ONLY
emi-le
52

vous pouvez toujours faire le prochain à l'avant, et juste faire une vérification post-boucle

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

    do {
     //statement(s)
    } while (resultSet.next());
}
Maslow
la source
21

Vous feriez généralement quelque chose comme ceci:

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

Si vous souhaitez signaler un ensemble vide, ajoutez une variable comptant les éléments lus. Si vous n'avez besoin de lire qu'un seul élément, votre code est suffisant.

kgiannakakis
la source
16

Pour être totalement sûr que le jeu de résultats est vide ou non, quelle que soit la position du curseur, je ferais quelque chose comme ceci:

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

Cette fonction retournera true si ResultSet est vide, false dans le cas contraire ou lèvera une exception SQLException si ce ResultSet est fermé / non initialisé.

Felype
la source
12

Il est préférable d'utiliser ResultSet.next () avec la syntaxe do {...} while () pour cela.

L'appel "vérifier les résultats" appelle ResultSet.next () déplace le curseur sur la première ligne, utilisez donc la syntaxe do {...} while () pour traiter cette ligne tout en continuant à traiter les lignes restantes renvoyées par la boucle.

De cette façon, vous pouvez vérifier les résultats, tout en traitant également les résultats renvoyés.

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());
}
Dermot Doherty
la source
8

Selon la réponse la plus viable, la suggestion est d'utiliser "isBeforeFirst ()". Ce n'est pas la meilleure solution si vous n'avez pas de "type de transfert uniquement" .

Il existe une méthode appelée " .first () ". Il est moins exagéré d'obtenir exactement le même résultat. Vous vérifiez s'il y a quelque chose dans votre "jeu de résultats" et vous ne faites pas avancer votre curseur.

La documentation indique: "(...) false s'il n'y a pas de lignes dans le jeu de résultats ".

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

Vous pouvez également simplement appeler isBeforeFirst () pour tester s'il y a des lignes retournées sans faire avancer le curseur, puis procédez normalement. - SnakeDoc du 2 septembre 2014 à 19h00

Cependant, il existe une différence entre "isBeforeFirst ()" et "first ()". Génère d'abord une exception si elle est effectuée sur un jeu de résultats de type "avant uniquement".

Comparez les deux sections de projection : 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 ()

D'accord, cela signifie que vous devez utiliser "isBeforeFirst" tant que vous avez un type "avant uniquement". Sinon, il est moins exagéré d'utiliser "first ()".

OddDev
la source
1
Comment est-il «moins exagéré» d'obtenir exactement le même résultat? Il me semble que l'objectif de first () est de déplacer le curseur sur la première ligne s'il n'est pas déjà là (et de retourner true s'il a réussi). isBeforeFirst est uniquement une fonction de diagnostic et semble plus adaptée aux objectifs de l'auteur. De plus, la façon dont first () est libellé, il renvoie vrai tant qu'il est "sur une ligne valide" ... ce qui est étrange comme on pourrait penser qu'il serait libellé comme "sur la première ligne". Pour moi, je ne vois pas l'avantage d'utiliser first () dans ce scénario à moins que votre curseur n'ait avancé et que vous ne souhaitiez le ramener au début.
Jon
5

Cela fonctionnerait si vous voulez voir s'il y a des lignes dans le jeu de résultats oui.

Notez que next()vous passez toujours à la ligne suivante, donc si vous prévoyez de faire une lecture de l'ensemble de résultats, vous devez en tenir compte.

L'utilisation habituelle avec ResultSet (lors de la simple lecture) est:

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

Ce qui évidemment ne fonctionnera pas correctement si vous avez next()déjà invoqué une fois pour vérifier si le jeu de résultats était vide, alors faites attention à cela. Bien qu'il existe des méthodes de «sauvegarde», elles ne sont pas prises en charge pour tous les types d'ensembles de résultats.

Nuoji
la source
5

Je pense que c'est un article pratique et facile à lire.

        if (res.next()) {
            do {

                // successfully in. do the right things.

            } while (res.next());
        } else {
           // no results back. warn the user.
        }
JSBach
la source
2
if (!resultSet.isAfterLast() ) {    
System.out.println("No data"); 
} 

isAfterLast() renvoie également false pour un jeu de résultats vide mais puisque le curseur est de toute façon avant la première ligne, cette méthode semble plus claire.

Nick Warke
la source
2
if(resultSet.first) {

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

Parce que si ResultSet n'a pas de brut, resultSet.firstrenvoie false.

user868927
la source
Mais cela déplace le curseur vers la première ligne inutile, et cela peut perturber l'utilisation de l'objet "réinitialiser" ob et peut perdre des données
Tigran Babajanyan
Bien que cela semble mieux, cela ne fonctionnera pas sur un jeu de résultats de curseur vers l'avant uniquement.
eliteproxy
1

La meilleure chose à faire est de vérifier la première ligne de sorte que lorsque vous avez l'intention d'obtenir les données, vous puissiez éviter l'erreur de sauter une ligne. Quelque chose comme: if (! ResultSet.first ()) {System.out.println ("no data"); }

Anthony Oyovwe
la source
1

En utilisant resultSet.next (), vous pouvez facilement obtenir le résultat, que resultSet contienne une valeur ou non

ResultSet resultSet = preparedStatement.executeQuery();
if(resultSet.next())
 //resultSet contain some values
else
 // empty resultSet
Ram72119
la source
Ne répétez pas les réponses existantes.
james.garriss
1
ResultSet result = stmt.executeQuery(sqlQuery);
if (!result.next())
    status = "ERROR";
else
    status = "SUCCESS";
Deepu Surendran
la source
1

J'ai essayé de définir la ligne actuelle sur le premier index (traitant des clés primaires). je voudrais suggerer

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

Lorsque le ResultSet est rempli, il pointe avant la première ligne. Lorsque vous la définissez sur la première ligne (indiquée par rs.absolute(1)), elle renvoie true indiquant qu'elle a été correctement placée à la ligne 1, ou false si la ligne n'existe pas. Nous pouvons extrapoler ceci à

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

ce qui définit la ligne actuelle à la position i et échouera si la ligne n'existe pas. Ceci est juste une méthode alternative à

while(rs.next()){
    //Code
}
Andrew
la source
Quelle est ta réponse?
CMedina
1

J'ai créé la méthode suivante pour vérifier si un ResultSet est vide.

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;
    }
}

Il est très important d'avoir les considérations suivantes:

L' objet CallableStatement doit être défini pour laisser l'objet ResultSet aller à la fin et revenir en haut.

TYPE_SCROLL_SENSITIVE : l'objet ResultSet peut se déplacer à la fin et revenir en haut. En outre, vous pouvez attraper les derniers changements.

CONCUR_READ_ONLY : Nous pouvons lire les données de l'objet ResultSet, mais ne pouvons pas les mettre à jour.

CallableStatement proc = dbconex.prepareCall(select, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
Cristian
la source
1

Je pense que le moyen le plus simple de vérifier l'ensemble de résultats est via CollectionUtils sous le package org.apache.commons.collections.CollectionUtils

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

Cela vérifiera la condition de jeu de résultats vide et vide.

Pour plus d'informations, vous pouvez vous référer au document suivant. CollectionUtils

Mitul Maheshwari
la source
1
ResultSet n'est pas une collection.
Joachim Lous
1

Pourquoi ne pas utiliser rs.getRow ()?

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

Pour moi, cochez "si (rs.getRow ()! = 0)" semble fonctionner très bien.

stiebrs
la source
0

vous pouvez faire quelque chose comme ça

boolean found = false;

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

if (!found)
    System.out.println("No Data");
Mohamed EL-Shabrawy
la source
1
WAAAY trop compliqué.
jordaniac89
0
ResultSet rs = rs.executeQuery();
if(rs.next())
{
  rs = rs.executeQuery();
  while(rs.next())
  {
    //do code part
  }
}
else
{
  //else if no result set
}

Il est préférable de réexécuter la requête car lorsque nous appelons la if(rs.next()){....}première ligne de ResultSet sera exécutée et après elle à l'intérieur, while(rs.next()){....}nous obtiendrons le résultat de la ligne suivante. Je pense donc que la réexécution de la requête à l'intérieur ifest la meilleure option.

Arpit Trivedi
la source
5
-1 Ce n'est pas une meilleure option. Pourquoi interroger la base de données deux fois? Et si les données changent radicalement entre les appels? C'est du gaspillage.
Toby Caulk
-2

Initialement, l'objet du jeu de résultats (rs) pointe vers le BFR (avant le premier enregistrement). Une fois que nous utilisons rs.next (), le curseur pointe vers le premier enregistrement et le rs est "vrai". En utilisant la boucle while, vous pouvez imprimer tous les enregistrements de la table. Une fois tous les enregistrements récupérés, le curseur se déplace sur ALR (après le dernier enregistrement) et il est défini sur null. Considérons qu'il y a 2 enregistrements dans le tableau.

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

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

En bref, nous pouvons également écrire la condition sous la forme while (rs.next ()).

Shiva
la source
3
Votre boucle while n'aura pas la possibilité de fonctionner sur la première ligne renvoyée, ce qui semble un défaut quelque peu fatal avec cette approche. Il y a beaucoup de suggestions ci-dessus qui sont meilleures que celle-ci.
Jules