¿No debería ser una operación bastante sencilla? Sin embargo, veo que hay ni una size()
ni length()
método.
¿No debería ser una operación bastante sencilla? Sin embargo, veo que hay ni una size()
ni length()
método.
Respuestas:
Haz una SELECT COUNT(*) FROM ...
consulta en su lugar.
O
int size =0;
if (rs != null)
{
rs.last(); // moves cursor to the last row
size = rs.getRow(); // get row id
}
En cualquiera de los casos, no tendrá que recorrer todos los datos.
select count
?
ResultSet#last()
no funciona en todo tipo de ResultSet
objetos, debe asegurarse de usar uno que sea ResultSet.TYPE_SCROLL_INSENSITIVE
oResultSet.TYPE_SCROLL_SENSITIVE
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
}
getRow()
funciona para TYPE_FORWARD_ONLY
ResultSets y beforeFirst()
arroja errores para ellos. ¿No es esta respuesta defectuosa entonces?
ps=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
Bueno, si tiene un ResultSet
tipo ResultSet.TYPE_FORWARD_ONLY
, desea mantenerlo de esa manera (y no cambiar a uno ResultSet.TYPE_SCROLL_INSENSITIVE
o ResultSet.TYPE_SCROLL_INSENSITIVE
para poder usarlo .last()
).
Sugiero un hack muy agradable y eficiente, donde agregas una primera fila falsa / falsa en la parte superior que contiene el número de filas.
Ejemplo
Digamos que su consulta es la siguiente
select MYBOOL,MYINT,MYCHAR,MYSMALLINT,MYVARCHAR
from MYTABLE
where ...blahblah...
y su salida se ve como
true 65537 "Hey" -32768 "The quick brown fox"
false 123456 "Sup" 300 "The lazy dog"
false -123123 "Yo" 0 "Go ahead and jump"
false 3 "EVH" 456 "Might as well jump"
...
[1000 total rows]
Simplemente refactorice su código a algo como esto:
Statement s=myConnection.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY);
String from_where="FROM myTable WHERE ...blahblah... ";
//h4x
ResultSet 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);
Su salida de consulta ahora será algo así como
1000 null null null null null
null true 65537 "Hey" -32768 "The quick brown fox"
null false 123456 "Sup" 300 "The lazy dog"
null false -123123 "Yo" 0 "Go ahead and jump"
null false 3 "EVH" 456 "Might as well jump"
...
[1001 total rows]
Entonces solo tienes que
if(rs.next())
System.out.println("Recordcount: "+rs.getInt("RECORDCOUNT"));//hack: first record contains the record count
while(rs.next())
//do your stuff
ResultSet.TYPE_FORWARD_ONLY
)
int i = 0;
while(rs.next()) {
i++;
}
Tengo una excepción cuando uso rs.last()
if(rs.last()){
rowCount = rs.getRow();
rs.beforeFirst();
}
:
java.sql.SQLException: Invalid operation for forward only resultset
es debido a que es por defecto ResultSet.TYPE_FORWARD_ONLY
, lo que significa que solo puedes usarrs.next()
la solucion es:
stmt=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
ResultSet.TYPE_FORWARD_ONLY
a ResultSet.TYPE_SCROLL_INSENSITIVE
generalmente conlleva una gran penalización de rendimiento.
SELECT COUNT(*) FROM default_tbl
antes SELECT COUNT(*) FROM default_tbl
, tardé menos de 1,5 segundos. Probé en la base de datos de derby incorporada 10.11.1.1
La forma de obtener el tamaño de ResultSet, sin necesidad de usar ArrayList, etc.
int size =0;
if (rs != null)
{
rs.beforeFirst();
rs.last();
size = rs.getRow();
}
Ahora obtendrá el tamaño, y si desea imprimir el ResultSet, antes de imprimir use también la siguiente línea de código,
rs.beforeFirst();
[Consideración de velocidad]
Gran cantidad de personas aquí sugiere, ResultSet.last()
pero para eso necesitaría abrir la conexión, ya ResultSet.TYPE_SCROLL_INSENSITIVE
que para la base de datos incrustada Derby es hasta 10 veces MÁS LENTO que ResultSet.TYPE_FORWARD_ONLY
.
Según mis micropruebas para las bases de datos Derby y H2 integradas, es mucho más rápido llamar SELECT COUNT(*)
antes de su SELECT.
Aquí está con más detalle mi código y mis puntos de referencia
Es una forma sencilla de hacer recuento de filas.
ResultSet rs = job.getSearchedResult(stmt);
int rsCount = 0;
//but notice that you'll only get correct ResultSet size after end of the while loop
while(rs.next())
{
//do your other per row stuff
rsCount = rsCount + 1;
}//end while
String sql = "select count(*) from message";
ps = cn.prepareStatement(sql);
rs = ps.executeQuery();
int rowCount = 0;
while(rs.next()) {
rowCount = Integer.parseInt(rs.getString("count(*)"));
System.out.println(Integer.parseInt(rs.getString("count(*)")));
}
System.out.println("Count : " + rowCount);
Verifiqué el valor de tiempo de ejecución de la interfaz ResultSet y descubrí que era casi un ResultSetImpl todo el tiempo. ResultSetImpl tiene un método llamado getUpdateCount()
que devuelve el valor que está buscando.
Esta muestra de código debería ser suficiente:
ResultSet resultSet = executeQuery(sqlQuery);
double rowCount = ((ResultSetImpl)resultSet).getUpdateCount()
Me doy cuenta de que el downcasting generalmente es un procedimiento inseguro, pero este método aún no me ha fallado.
java.lang.ClassCastException: org.apache.tomcat.dbcp.dbcp.DelegatingResultSet cannot be cast to com.mysql.jdbc.ResultSetImpl
Hoy, utilicé esta lógica por la que no sé cómo obtener el recuento 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();
Estaba teniendo el mismo problema. Utilizando ResultSet.first()
de esta manera justo después de que la ejecución lo resolvió:
if(rs.first()){
// Do your job
} else {
// No rows take some actions
}
Documentación ( enlace ):
boolean first() throws SQLException
Mueve el cursor a la primera fila de este
ResultSet
objeto.Devoluciones:
true
si el cursor está en una fila válida;false
si no hay filas en el conjunto de resultadosLanza
SQLException
- si se produce un error de acceso a la base de datos; Este método se llama en un conjunto de resultados cerrado o el tipo de conjunto de resultados esTYPE_FORWARD_ONLY
SQLFeatureNotSupportedException
- si el controlador JDBC no admite este métodoYa que:
1,2
Enfoque más fácil, consulta Run Count (*), haz resultSet.next () para apuntar a la primera fila y luego haz resultSet.getString (1) para obtener el conteo. Código:
ResultSet rs = statement.executeQuery("Select Count(*) from your_db");
if(rs.next()) {
int count = rs.getString(1).toInt()
}
Dale un nombre a la columna.
String query = "SELECT COUNT(*) as count FROM
Haga referencia a esa columna del objeto ResultSet en un int y haga su lógica desde allí.
PreparedStatement statement = connection.prepareStatement(query);
statement.setString(1, item.getProductId());
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()) {
int count = resultSet.getInt("count");
if (count >= 1) {
System.out.println("Product ID already exists.");
} else {
System.out.println("New Product ID.");
}
}