Zrozumiałem pytanie, że chcesz znaleźć rozmiar zestawu wyników w bajtach, a nie liczbę krotek ...
DejanLekic
Bardzo denerwujące jest to, że nie ma właściwego wymiaru przed przetwarzaniem danych, ale jeśli musisz przechowywać je w tablicy, możesz rozważyć użycie struktury danych takiej jak List, a następnie przekonwertować je na tablicę za pomocą metody toArray ().
AndreaTaroni86
Odpowiedzi:
270
SELECT COUNT(*) FROM ...Zamiast tego wykonaj zapytanie.
LUB
int size =0;if(rs !=null){
rs.last();// moves cursor to the last row
size = rs.getRow();// get row id }
W obu przypadkach nie będziesz musiał zapętlać całych danych.
last () i getRow () nie są metodami statycznymi w klasie ResultSet.
JeeBee,
70
Dla zwięzłości zawsze piszę o metodach w ten sposób, pisząc o nich innym, bez względu na to, czy są one statyczne, czy nie. W rzeczywistości zakłada się utworzenie instancji obiektu i wywołanie metody.
laz
51
Piszę SomeClass.staticMethod () i SomeClass # instanceMethod () dla mniejszego zamieszania.
Jake
9
Jak pobrać wartość zwróconą podczas wykonywania select count?
Naftuli Kay
16
ResultSet#last()nie działa na wszystkich typach ResultSetobiektów, musisz upewnić się, że używasz jednego z nich ResultSet.TYPE_SCROLL_INSENSITIVElubResultSet.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}
Czy w bloku kodu if (rs.last ()) poprawną metodą nie byłoby rs.beforeFirst () zamiast rs.first ()? W ten sposób nie pomijasz pierwszego rekordu w zestawie wyników do przetwarzania w pętli while.
karlgrz
nie zapomnij ustawić z powrotem kursora na pozycję Pierwsze na zewnątrz bloku if?
Gobliins,
Jak mówią dokumenty ResultSet , getRow()działa dla TYPE_FORWARD_ONLYResultSets i beforeFirst()zgłasza dla nich błędy. Czy więc ta odpowiedź nie jest błędna?
CodePro_NotYet
5
Działa to tylko wtedy, gdy instrukcja jest tworzona z opcją niewrażliwą na przewijanie:ps=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
BullyWiiPlaza
19
Cóż, jeśli masz ResultSettypu ResultSet.TYPE_FORWARD_ONLYchcesz zachować to w ten sposób (i nie przełączyć się na ResultSet.TYPE_SCROLL_INSENSITIVElub ResultSet.TYPE_SCROLL_INSENSITIVEw celu umożliwienia użytkowania .last()).
Sugeruję bardzo fajny i wydajny hack, w którym dodajesz pierwszy fałszywy / fałszywy wiersz na górze zawierający liczbę wierszy.
Przykład
Powiedzmy, że twoje zapytanie jest następujące
select MYBOOL,MYINT,MYCHAR,MYSMALLINT,MYVARCHAR
from MYTABLE
where...blahblah...
a twój wygląd wygląda
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]
Po prostu popraw kod na coś takiego:
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);
Dane wyjściowe zapytania będą teraz podobne
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]
Musisz po prostu
if(rs.next())System.out.println("Recordcount: "+rs.getInt("RECORDCOUNT"));//hack: first record contains the record countwhile(rs.next())//do your stuff
Ciekawe, ale jak byś generował dynamicznie / generalnie pierwsze instrukcje select: cast (null as boolean) jako MYBOOL, ect? W tym celu potrzebujesz metadanych pól i typów danych instrukcji „select”, takich jak boolean, char, int, ect ...), które mogą wymagać dodatkowej podróży DB, która neguje wszystkie korzyści.
user1697575,
Jest to przydatne, gdy masz dostęp do wszystkich szczegółów pola, a najważniejsza jest prędkość (i dlatego musisz trzymać się postu ResultSet.TYPE_FORWARD_ONLY)
Nie rozumiem, jaka jest wada używania tej metody do obliczania rozmiaru zestawu wyników. To wspaniale ... bez użycia dodatkowego parametru SQL. Proszę skomentować tę metodę.
Madeyedexter
5
Wydajność jest tutaj słowem kluczowym. Wyobraź sobie, że Twój zestaw wyników to 100 milionów rekordów, a wtedy zobaczysz problem
Pierre,
7
Chcę poznać rozmiar zestawu wyników PRZED przetworzeniem wyników, ponieważ muszę wcześniej utworzyć tablicę o tym samym rozmiarze. I, jak zauważono w innych odpowiedziach, skanowanie wszystkich wierszy dwa razy nie zawsze będzie działać.
Przełączanie z ResultSet.TYPE_FORWARD_ONLYna ResultSet.TYPE_SCROLL_INSENSITIVEogół pociąga za sobą w wielkim spadku wydajności.
Unai Vivi
3
Testowałem to na moim stole (10 kolumn, 187 392 wierszy). Mój test wykonał zapytanie i załadował wszystkie elementy do łańcucha. Dla TYPE_FORWARD_ONLY zajęło to około 1 sekundy. Dla TYPE_SCROLL_INSENSITIVE zajęło to około 7 sekund. Kiedy użyłem SELECT COUNT(*) FROM default_tblwcześniej SELECT COUNT(*) FROM default_tbl, zajęło to mniej niż 1,5 sekundy. Testowałem na wbudowanej bazie danych derby 10.11.1.1
Vit Bernatik
4
Sposób uzyskania rozmiaru ResultSet, nie ma potrzeby używania ArrayList itp
int size =0;if(rs !=null){
rs.beforeFirst();
rs.last();
size = rs.getRow();}
Teraz otrzymasz rozmiar, a jeśli chcesz wydrukować zestaw wyników, przed wydrukowaniem użyj również następującego wiersza kodu,
Wiele ppl tutaj sugeruje, ResultSet.last()ale do tego trzeba by otworzyć połączenie, ponieważ ResultSet.TYPE_SCROLL_INSENSITIVEdla wbudowanej bazy danych Derby jest do 10 razy wolniejsze niż ResultSet.TYPE_FORWARD_ONLY.
Według moich mikrotestów dla osadzonych baz danych Derby i H2 znacznie szybciej jest zadzwonić SELECT COUNT(*)przed 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
Tak, to działa. Ale myślę, że OP boryka się ze znajomością liczby wierszy, zanim faktycznie je przetworzy. Prawdziwe powody, dla których musiałbym do tej pory walczyć z tym problemem: 1.) stronicowanie rekordowych wierszy 2.) pokazywanie wierszy przetworzonych w długo trwających zadaniach do celów monitorowania postępów ...
ppeterka
Innym powodem jest wstępne przydzielanie wielkości struktury danych. Widziałem, że wiele bibliotek zwraca 10 list Element, gdy jest tylko jedna wartość, ponieważ deweloper miał ten sam problem z ResultSet.
Sprawdziłem wartość środowiska uruchomieniowego interfejsu ResultSet i odkryłem, że przez cały czas była to w zasadzie ResultSetImpl . ResultSetImpl ma wywoływaną metodę, getUpdateCount()która zwraca poszukiwaną wartość.
Ten przykładowy kod powinien wystarczyć: ResultSet resultSet = executeQuery(sqlQuery); double rowCount = ((ResultSetImpl)resultSet).getUpdateCount()
Zdaję sobie sprawę, że downcasting jest ogólnie niebezpieczną procedurą, ale ta metoda jeszcze mnie nie zawiodła.
Nie działa z Tomcat / MySQL:java.lang.ClassCastException: org.apache.tomcat.dbcp.dbcp.DelegatingResultSet cannot be cast to com.mysql.jdbc.ResultSetImpl
Panu Haaramo
1
Dzisiaj użyłem tej logiki, dlaczego nie wiem, jak uzyskać liczbę 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();
Przenosi kursor do pierwszego wiersza w tym ResultSetobiekcie.
Zwroty:
truejeśli kursor znajduje się w poprawnym wierszu; falsejeśli nie ma wierszy w zestawie wyników
Rzuty:
SQLException- jeśli wystąpi błąd dostępu do bazy danych; ta metoda jest wywoływana dla zamkniętego zestawu wyników lub typem zestawu wyników jestTYPE_FORWARD_ONLY
Najłatwiejsze podejście, zapytanie Run Count (*), wykonaj resultSet.next (), aby wskazać pierwszy wiersz, a następnie po prostu wykonaj wynikSet.getString (1), aby uzyskać liczbę. Kod :
ResultSet rs = statement.executeQuery("Select Count(*) from your_db");if(rs.next()){int count = rs.getString(1).toInt()}
Odpowiedzi:
SELECT COUNT(*) FROM ...
Zamiast tego wykonaj zapytanie.LUB
W obu przypadkach nie będziesz musiał zapętlać całych danych.
źródło
select count
?ResultSet#last()
nie działa na wszystkich typachResultSet
obiektów, musisz upewnić się, że używasz jednego z nichResultSet.TYPE_SCROLL_INSENSITIVE
lubResultSet.TYPE_SCROLL_SENSITIVE
źródło
getRow()
działa dlaTYPE_FORWARD_ONLY
ResultSets ibeforeFirst()
zgłasza dla nich błędy. Czy więc ta odpowiedź nie jest błędna?ps=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
Cóż, jeśli masz
ResultSet
typuResultSet.TYPE_FORWARD_ONLY
chcesz zachować to w ten sposób (i nie przełączyć się naResultSet.TYPE_SCROLL_INSENSITIVE
lubResultSet.TYPE_SCROLL_INSENSITIVE
w celu umożliwienia użytkowania.last()
).Sugeruję bardzo fajny i wydajny hack, w którym dodajesz pierwszy fałszywy / fałszywy wiersz na górze zawierający liczbę wierszy.
Przykład
Powiedzmy, że twoje zapytanie jest następujące
a twój wygląd wygląda
Po prostu popraw kod na coś takiego:
Dane wyjściowe zapytania będą teraz podobne
Musisz po prostu
źródło
ResultSet.TYPE_FORWARD_ONLY
)źródło
Mam wyjątek podczas używania
rs.last()
:
jest to spowodowane domyślnie
ResultSet.TYPE_FORWARD_ONLY
, co oznacza, że możesz używać tylkors.next()
rozwiązaniem jest:
źródło
ResultSet.TYPE_FORWARD_ONLY
naResultSet.TYPE_SCROLL_INSENSITIVE
ogół pociąga za sobą w wielkim spadku wydajności.SELECT COUNT(*) FROM default_tbl
wcześniejSELECT COUNT(*) FROM default_tbl
, zajęło to mniej niż 1,5 sekundy. Testowałem na wbudowanej bazie danych derby 10.11.1.1Sposób uzyskania rozmiaru ResultSet, nie ma potrzeby używania ArrayList itp
Teraz otrzymasz rozmiar, a jeśli chcesz wydrukować zestaw wyników, przed wydrukowaniem użyj również następującego wiersza kodu,
źródło
[Uwzględnienie prędkości]
Wiele ppl tutaj sugeruje,
ResultSet.last()
ale do tego trzeba by otworzyć połączenie, ponieważResultSet.TYPE_SCROLL_INSENSITIVE
dla wbudowanej bazy danych Derby jest do 10 razy wolniejsze niżResultSet.TYPE_FORWARD_ONLY
.Według moich mikrotestów dla osadzonych baz danych Derby i H2 znacznie szybciej jest zadzwonić
SELECT COUNT(*)
przed SELECT.Oto bardziej szczegółowo mój kod i moje testy porównawcze
źródło
Jest to prosty sposób na liczenie wierszy.
źródło
źródło
Sprawdziłem wartość środowiska uruchomieniowego interfejsu ResultSet i odkryłem, że przez cały czas była to w zasadzie ResultSetImpl . ResultSetImpl ma wywoływaną metodę,
getUpdateCount()
która zwraca poszukiwaną wartość.Ten przykładowy kod powinien wystarczyć:
ResultSet resultSet = executeQuery(sqlQuery);
double rowCount = ((ResultSetImpl)resultSet).getUpdateCount()
Zdaję sobie sprawę, że downcasting jest ogólnie niebezpieczną procedurą, ale ta metoda jeszcze mnie nie zawiodła.
źródło
java.lang.ClassCastException: org.apache.tomcat.dbcp.dbcp.DelegatingResultSet cannot be cast to com.mysql.jdbc.ResultSetImpl
Dzisiaj użyłem tej logiki, dlaczego nie wiem, jak uzyskać liczbę RS.
źródło
źródło
Miałem ten sam problem. Używając
ResultSet.first()
w ten sposób zaraz po rozwiązaniu wykonania:Dokumentacja ( link ):
źródło
Najłatwiejsze podejście, zapytanie Run Count (*), wykonaj resultSet.next (), aby wskazać pierwszy wiersz, a następnie po prostu wykonaj wynikSet.getString (1), aby uzyskać liczbę. Kod :
źródło
Nadaj kolumnie nazwę…
Odwołaj się do tej kolumny z obiektu ResultSet do int i wykonaj swoją logikę stamtąd.
źródło