J'adorerais connaître la raison de cette omission.
Slamice
Ma compréhension de la question était que vous vouliez trouver la taille du ResultSet IN BYTES, pas le nombre de tuples ...
DejanLekic
Il est très ennuyeux de ne pas avoir la bonne dimension avant de traiter les données, mais si vous devez les stocker dans un tableau, vous pouvez envisager d'utiliser une structure de données comme List, puis les convertir en un tableau avec la méthode toArray ().
AndreaTaroni86
Réponses:
270
Faites SELECT COUNT(*) FROM ...plutôt une requête.
OU
int size =0;if(rs !=null){
rs.last();// moves cursor to the last row
size = rs.getRow();// get row id }
Dans les deux cas, vous n'aurez pas à parcourir toutes les données.
last () et getRow () ne sont pas des méthodes statiques dans la classe ResultSet.
JeeBee
70
Par souci de concision, je fais toujours référence aux méthodes de cette façon lorsque j'écris à leur sujet aux autres, qu'elles soient statiques ou non. La création d'une instance de l'objet et l'appel de la méthode sont implicites.
laz
51
J'écris SomeClass.staticMethod () et SomeClass # instanceMethod () pour moins de confusion.
Jake
9
Comment récupérer la valeur retournée lors de l'exécution d'un select count?
Naftuli Kay
16
ResultSet#last()ne fonctionne pas sur tous les types d' ResultSetobjets, vous devez vous assurer d' utiliser celui qui est soit ResultSet.TYPE_SCROLL_INSENSITIVEouResultSet.TYPE_SCROLL_SENSITIVE
Marius Ion
91
ResultSet rs = ps.executeQuery();int rowcount =0;if(rs.last()){
rowcount = rs.getRow();
rs.beforeFirst();// not rs.first() because the rs.next() below will move on, missing the first element}while(rs.next()){// do your standard per row stuff}
Dans le bloc de code if (rs.last ()), la bonne méthode ne serait-elle pas rs.beforeFirst () au lieu de rs.first ()? De cette façon, vous ne sautez pas le premier enregistrement de votre jeu de résultats pour le traitement dans la boucle while.
karlgrz le
n'oubliez pas de remettre le curseur sur beforeFirst en dehors du bloc if?
Gobliins
Comme le disent les documents ResultSet , getRow()fonctionne pour TYPE_FORWARD_ONLYResultSets et beforeFirst()génère des erreurs pour ceux-ci. Cette réponse n'est-elle pas défectueuse alors?
CodePro_NotYet
5
Cela ne fonctionne que lorsque l'instruction est créée avec l'option de défilement insensible:ps=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
BullyWiiPlaza
19
Eh bien, si vous avez un ResultSettype, ResultSet.TYPE_FORWARD_ONLYvous devez le conserver de cette façon (et ne pas passer à un ResultSet.TYPE_SCROLL_INSENSITIVEou ResultSet.TYPE_SCROLL_INSENSITIVEpour pouvoir l'utiliser .last()).
Je suggère un hack très agréable et efficace, où vous ajoutez une première ligne fausse / bidon en haut contenant le nombre de lignes.
Exemple
Disons que votre requête est la suivante
select MYBOOL,MYINT,MYCHAR,MYSMALLINT,MYVARCHAR
from MYTABLE
where...blahblah...
et votre sortie ressemble
true65537"Hey"-32768"The quick brown fox"false123456"Sup"300"The lazy dog"false-123123"Yo"0"Go ahead and jump"false3"EVH"456"Might as well jump"...[1000 total rows]
Réorganisez simplement votre code en quelque chose comme ceci:
Statement s=myConnection.createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_READ_ONLY);String from_where="FROM myTable WHERE ...blahblah... ";//h4xResultSet rs=s.executeQuery("select count(*)as RECORDCOUNT,"+"cast(null as boolean)as MYBOOL,"+"cast(null as int)as MYINT,"+"cast(null as char(1))as MYCHAR,"+"cast(null as smallint)as MYSMALLINT,"+"cast(null as varchar(1))as MYVARCHAR "+from_where
+"UNION ALL "//the "ALL" part prevents internal re-sorting to prevent duplicates (and we do not want that)+"select cast(null as int)as RECORDCOUNT,"+"MYBOOL,MYINT,MYCHAR,MYSMALLINT,MYVARCHAR "+from_where);
La sortie de votre requête sera maintenant quelque chose comme
1000nullnullnullnullnullnulltrue65537"Hey"-32768"The quick brown fox"nullfalse123456"Sup"300"The lazy dog"nullfalse-123123"Yo"0"Go ahead and jump"nullfalse3"EVH"456"Might as well jump"...[1001 total rows]
Il vous suffit donc de
if(rs.next())System.out.println("Recordcount: "+rs.getInt("RECORDCOUNT"));//hack: first record contains the record countwhile(rs.next())//do your stuff
Intéressant, mais comment généreriez-vous dynamiquement / génériquement les premières instructions select: cast (null comme booléen) en MYBOOL, ect? Pour cela, vous aurez besoin de métadonnées des champs et des types de données de l'instruction "select", comme booléen, char, int, ect ...) qui pourraient nécessiter un voyage DB supplémentaire qui annulera tous les avantages.
user1697575
Ceci est utile lorsque vous avez accès à tous les détails du terrain et que la vitesse est votre principale préoccupation (et que vous devez donc vous en tenir à un jeûne ResultSet.TYPE_FORWARD_ONLY)
Je ne comprends pas quel est l'inconvénient d'utiliser cette méthode pour calculer la taille de ResultSet. C'est super ... pas d'utilisation d'un paramètre SQL supplémentaire. Veuillez commenter cette méthode.
Madeyedexter
5
La performance est le mot clé ici. Imaginez que votre jeu de résultats compte 100 millions d'enregistrements, vous verrez le problème
Pierre
7
Je veux connaître la taille du jeu de résultats AVANT de traiter les résultats, car je dois au préalable créer un tableau de la même taille. Et, comme indiqué dans d'autres réponses, l'analyse de toutes les lignes deux fois ne fonctionnera pas toujours.
Ivo
11
J'ai une exception lors de l'utilisation rs.last()
Passer de ResultSet.TYPE_FORWARD_ONLYà ResultSet.TYPE_SCROLL_INSENSITIVEentraîne généralement une énorme pénalité de performance.
Unai Vivi
3
Je l'ai testé sur ma table (10 colonnes, 187 392 lignes). Mon test a interrogé et chargé tous les éléments dans la chaîne. Pour TYPE_FORWARD_ONLY, cela a pris environ 1 seconde. Pour TYPE_SCROLL_INSENSITIVE, il a fallu environ 7 secondes. Quand je l'ai utilisé plutôt SELECT COUNT(*) FROM default_tblavant, SELECT COUNT(*) FROM default_tblil a fallu au total moins de 1,5 seconde. J'ai testé sur la base de données derby intégrée 10.11.1.1
Vit Bernatik
4
La façon d'obtenir la taille de ResultSet, pas besoin d'utiliser ArrayList, etc.
int size =0;if(rs !=null){
rs.beforeFirst();
rs.last();
size = rs.getRow();}
Maintenant, vous obtiendrez la taille, et si vous voulez imprimer le ResultSet, avant d'imprimer, utilisez également la ligne de code suivante,
Beaucoup de ppl suggèrent ici, ResultSet.last()mais pour cela, vous devez ouvrir une connexion ResultSet.TYPE_SCROLL_INSENSITIVEqui, pour la base de données intégrée Derby, est jusqu'à 10 fois plus lente queResultSet.TYPE_FORWARD_ONLY .
Selon mes micro-tests pour les bases de données Derby et H2 intégrées, il est beaucoup plus rapide d'appeler SELECT COUNT(*)avant votre SELECT.
ResultSet rs = job.getSearchedResult(stmt);int rsCount =0;//but notice that you'll only get correct ResultSet size after end of the while loopwhile(rs.next()){//do your other per row stuff
rsCount = rsCount +1;}//end while
Ouais, ça marche. Mais je pense que l'OP a du mal à connaître le nombre de lignes avant de les traiter. Des raisons réelles pour lesquelles je devrais lutter contre ce problème jusqu'à présent: 1.) pagination des lignes d'enregistrement 2.) montrant les lignes traitées dans les tâches de longue durée à des fins de suivi des progrès ...
ppeterka
La préallocation de la taille de la structure de données est une autre raison. J'ai vu beaucoup de bibliothèques renvoyer 10 listes d'éléments lorsqu'il n'y a qu'une seule valeur car les développeurs ont eu le même problème avec ResultSet.
J'ai vérifié la valeur d'exécution de l' interface ResultSet et j'ai découvert que c'était à peu près tout le temps un ResultSetImpl . ResultSetImpl a une méthode appeléegetUpdateCount() qui renvoie la valeur que vous recherchez.
Cet exemple de code devrait suffire: ResultSet resultSet = executeQuery(sqlQuery); double rowCount = ((ResultSetImpl)resultSet).getUpdateCount()
Je me rends compte que le downcasting est généralement une procédure dangereuse mais cette méthode ne m'a pas encore échoué.
Ne fonctionne pas avec Tomcat / MySQL:java.lang.ClassCastException: org.apache.tomcat.dbcp.dbcp.DelegatingResultSet cannot be cast to com.mysql.jdbc.ResultSetImpl
Panu Haaramo
1
Aujourd'hui, j'ai utilisé cette logique pourquoi je ne sais pas obtenir le nombre de RS.
int chkSize =0;if(rs.next()){do{..... blah blah
enter code here for each rs.
chkSize++;}while(rs.next());}else{
enter code here for rs size =0}// good luck to u.
theStatement=theConnection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);ResultSet theResult=theStatement.executeQuery(query);//Get the size of the data returned
theResult.last();int size = theResult.getRow()* theResult.getMetaData().getColumnCount();
theResult.beforeFirst();
Déplace le curseur sur la première ligne de cet ResultSetobjet.
Retour:
truesi le curseur se trouve sur une ligne valide; falses'il n'y a pas de lignes dans le jeu de résultats
Jette:
SQLException- si une erreur d'accès à la base de données se produit; cette méthode est appelée sur un jeu de résultats fermé ou le type de jeu de résultats estTYPE_FORWARD_ONLY
Approche la plus simple, exécutez la requête Count (*), effectuez resultSet.next () pour pointer vers la première ligne, puis effectuez simplement resultSet.getString (1) pour obtenir le nombre. Code:
ResultSet rs = statement.executeQuery("Select Count(*) from your_db");if(rs.next()){int count = rs.getString(1).toInt()}
Réponses:
Faites
SELECT COUNT(*) FROM ...
plutôt une requête.OU
Dans les deux cas, vous n'aurez pas à parcourir toutes les données.
la source
select count
?ResultSet#last()
ne fonctionne pas sur tous les types d'ResultSet
objets, vous devez vous assurer d' utiliser celui qui est soitResultSet.TYPE_SCROLL_INSENSITIVE
ouResultSet.TYPE_SCROLL_SENSITIVE
la source
getRow()
fonctionne pourTYPE_FORWARD_ONLY
ResultSets etbeforeFirst()
génère des erreurs pour ceux-ci. Cette réponse n'est-elle pas défectueuse alors?ps=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
Eh bien, si vous avez un
ResultSet
type,ResultSet.TYPE_FORWARD_ONLY
vous devez le conserver de cette façon (et ne pas passer à unResultSet.TYPE_SCROLL_INSENSITIVE
ouResultSet.TYPE_SCROLL_INSENSITIVE
pour pouvoir l'utiliser.last()
).Je suggère un hack très agréable et efficace, où vous ajoutez une première ligne fausse / bidon en haut contenant le nombre de lignes.
Exemple
Disons que votre requête est la suivante
et votre sortie ressemble
Réorganisez simplement votre code en quelque chose comme ceci:
La sortie de votre requête sera maintenant quelque chose comme
Il vous suffit donc de
la source
ResultSet.TYPE_FORWARD_ONLY
)la source
J'ai une exception lors de l'utilisation
rs.last()
:
c'est dû par défaut à ce qu'il est
ResultSet.TYPE_FORWARD_ONLY
, ce qui signifie que vous ne pouvez utiliser quers.next()
la solution est:
la source
ResultSet.TYPE_FORWARD_ONLY
àResultSet.TYPE_SCROLL_INSENSITIVE
entraîne généralement une énorme pénalité de performance.SELECT COUNT(*) FROM default_tbl
avant,SELECT COUNT(*) FROM default_tbl
il a fallu au total moins de 1,5 seconde. J'ai testé sur la base de données derby intégrée 10.11.1.1La façon d'obtenir la taille de ResultSet, pas besoin d'utiliser ArrayList, etc.
Maintenant, vous obtiendrez la taille, et si vous voulez imprimer le ResultSet, avant d'imprimer, utilisez également la ligne de code suivante,
la source
[Considération de vitesse]
Beaucoup de ppl suggèrent ici,
ResultSet.last()
mais pour cela, vous devez ouvrir une connexionResultSet.TYPE_SCROLL_INSENSITIVE
qui, pour la base de données intégrée Derby, est jusqu'à 10 fois plus lente queResultSet.TYPE_FORWARD_ONLY
.Selon mes micro-tests pour les bases de données Derby et H2 intégrées, il est beaucoup plus rapide d'appeler
SELECT COUNT(*)
avant votre SELECT.Voici plus en détail mon code et mes benchmarks
la source
C'est un moyen simple de compter les lignes.
la source
la source
J'ai vérifié la valeur d'exécution de l' interface ResultSet et j'ai découvert que c'était à peu près tout le temps un ResultSetImpl . ResultSetImpl a une méthode appelée
getUpdateCount()
qui renvoie la valeur que vous recherchez.Cet exemple de code devrait suffire:
ResultSet resultSet = executeQuery(sqlQuery);
double rowCount = ((ResultSetImpl)resultSet).getUpdateCount()
Je me rends compte que le downcasting est généralement une procédure dangereuse mais cette méthode ne m'a pas encore échoué.
la source
java.lang.ClassCastException: org.apache.tomcat.dbcp.dbcp.DelegatingResultSet cannot be cast to com.mysql.jdbc.ResultSetImpl
Aujourd'hui, j'ai utilisé cette logique pourquoi je ne sais pas obtenir le nombre de RS.
la source
la source
J'avais le même problème. L'utilisation
ResultSet.first()
de cette manière juste après l'exécution l'a résolu:Documentation ( lien ):
la source
Approche la plus simple, exécutez la requête Count (*), effectuez resultSet.next () pour pointer vers la première ligne, puis effectuez simplement resultSet.getString (1) pour obtenir le nombre. Code:
la source
Donnez un nom à la colonne ..
Référencez cette colonne de l'objet ResultSet dans un int et faites votre logique à partir de là.
la source