Sollte dies nicht eine ziemlich einfache Operation sein? Ich sehe jedoch, dass es weder eine size()
noch eine length()
Methode gibt.
Sollte dies nicht eine ziemlich einfache Operation sein? Ich sehe jedoch, dass es weder eine size()
noch eine length()
Methode gibt.
Antworten:
SELECT COUNT(*) FROM ...
Führen Sie stattdessen eine Abfrage durch.
ODER
int size =0;
if (rs != null)
{
rs.last(); // moves cursor to the last row
size = rs.getRow(); // get row id
}
In beiden Fällen müssen Sie nicht die gesamten Daten durchlaufen.
select count
?
ResultSet#last()
funktioniert nicht bei allen Arten von ResultSet
Objekten, Sie müssen sicherstellen, dass Sie eines verwenden, das entweder ResultSet.TYPE_SCROLL_INSENSITIVE
oderResultSet.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()
funktioniert es für TYPE_FORWARD_ONLY
ResultSets und beforeFirst()
wirft Fehler für diese aus. Ist diese Antwort dann nicht fehlerhaft?
ps=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
Nun, wenn Sie einen ResultSet
Typ haben ResultSet.TYPE_FORWARD_ONLY
, möchten Sie ihn so lassen (und nicht zu einem ResultSet.TYPE_SCROLL_INSENSITIVE
oder wechseln, ResultSet.TYPE_SCROLL_INSENSITIVE
um ihn verwenden zu können .last()
).
Ich schlage einen sehr schönen und effizienten Hack vor, bei dem Sie oben eine erste falsche / falsche Zeile hinzufügen, die die Anzahl der Zeilen enthält.
Beispiel
Angenommen, Ihre Anfrage lautet wie folgt
select MYBOOL,MYINT,MYCHAR,MYSMALLINT,MYVARCHAR
from MYTABLE
where ...blahblah...
und Ihre Ausgabe sieht aus wie
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]
Refaktorieren Sie Ihren Code einfach wie folgt:
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);
Ihre Abfrageausgabe wird nun so etwas wie sein
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]
Also musst du einfach
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++;
}
Ich habe eine Ausnahme bei der Verwendung rs.last()
if(rs.last()){
rowCount = rs.getRow();
rs.beforeFirst();
}
::
java.sql.SQLException: Invalid operation for forward only resultset
Dies liegt standardmäßig daran ResultSet.TYPE_FORWARD_ONLY
, was bedeutet, dass Sie nur verwenden könnenrs.next()
Die Lösung ist:
stmt=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
ResultSet.TYPE_FORWARD_ONLY
zu führt ResultSet.TYPE_SCROLL_INSENSITIVE
normalerweise zu einem enormen Leistungsverlust.
SELECT COUNT(*) FROM default_tbl
vor dem benutzte SELECT COUNT(*) FROM default_tbl
, dauerte es insgesamt weniger als 1,5 Sekunden. Ich habe auf eingebetteten Derby-Datenbank 10.11.1.1
Die Methode zum Abrufen der Größe von ResultSet, keine Verwendung von ArrayList usw.
int size =0;
if (rs != null)
{
rs.beforeFirst();
rs.last();
size = rs.getRow();
}
Jetzt erhalten Sie die Größe. Wenn Sie das ResultSet drucken möchten, verwenden Sie vor dem Drucken auch die folgende Codezeile:
rs.beforeFirst();
[Geschwindigkeitsüberlegung]
Viele Leute hier schlagen vor, ResultSet.last()
aber dafür müssten Sie die Verbindung öffnen, da ResultSet.TYPE_SCROLL_INSENSITIVE
die für Derby eingebettete Datenbank bis zu 10-mal langsamer ist als ResultSet.TYPE_FORWARD_ONLY
.
Laut meinen Mikrotests für eingebettete Derby- und H2-Datenbanken ist es wesentlich schneller, SELECT COUNT(*)
vor Ihrem SELECT anzurufen .
Hier finden Sie detaillierter meinen Code und meine Benchmarks
Es ist eine einfache Möglichkeit, Zeilen zu zählen.
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);
Ich habe den Laufzeitwert der ResultSet- Schnittstelle überprüft und festgestellt, dass es sich die ganze Zeit über um ein ResultSetImpl handelt . ResultSetImpl hat eine Methode namens, getUpdateCount()
die den gesuchten Wert zurückgibt.
Dieses Codebeispiel sollte ausreichen:
ResultSet resultSet = executeQuery(sqlQuery);
double rowCount = ((ResultSetImpl)resultSet).getUpdateCount()
Mir ist klar, dass Downcasting im Allgemeinen ein unsicheres Verfahren ist, aber diese Methode hat mich noch nicht gescheitert.
java.lang.ClassCastException: org.apache.tomcat.dbcp.dbcp.DelegatingResultSet cannot be cast to com.mysql.jdbc.ResultSetImpl
Heute habe ich diese Logik verwendet, warum ich nicht weiß, wie man RS zählt.
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();
Ich hatte das gleiche Problem. Verwenden Sie ResultSet.first()
auf diese Weise direkt nach der Ausführung gelöst:
if(rs.first()){
// Do your job
} else {
// No rows take some actions
}
Dokumentation ( Link ):
boolean first() throws SQLException
Bewegt den Cursor in die erste Zeile dieses
ResultSet
Objekts.Kehrt zurück:
true
wenn sich der Cursor in einer gültigen Zeile befindet;false
wenn die Ergebnismenge keine Zeilen enthältWürfe:
SQLException
- wenn ein Datenbankzugriffsfehler auftritt; Diese Methode wird für eine geschlossene Ergebnismenge aufgerufen oder der Ergebnismengen-Typ istTYPE_FORWARD_ONLY
SQLFeatureNotSupportedException
- Wenn der JDBC-Treiber diese Methode nicht unterstütztSchon seit:
1.2
Am einfachsten ist es, die Abfrage Count (*) auszuführen, resultSet.next () auszuführen, um auf die erste Zeile zu zeigen, und dann einfach resultSet.getString (1) auszuführen, um die Anzahl abzurufen. Code:
ResultSet rs = statement.executeQuery("Select Count(*) from your_db");
if(rs.next()) {
int count = rs.getString(1).toInt()
}
Geben Sie der Spalte einen Namen.
String query = "SELECT COUNT(*) as count FROM
Verweisen Sie auf diese Spalte aus dem ResultSet-Objekt in ein int und führen Sie von dort aus Ihre Logik aus.
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.");
}
}