Bir java.sql.ResultSet boyutunu nasıl edinebilirim?


285

Bu oldukça basit bir işlem olmamalı mı? Ancak, ne bir size()ne de bir length()yöntem olduğunu görüyorum .


11
Bu ihmalin nedenini bilmek isterim.
Slamice

Soruya ilişkin anlayışım, tuples sayısını değil,
BYTES'deki

İşlem verilerinden önce doğru boyuta sahip olmak çok can sıkıcıdır, ancak bunları bir dizide saklamanız gerekiyorsa, List gibi bir veri yapısı kullanmayı ve ardından toArray () yöntemiyle bir diziye dönüştürebilirsiniz.
AndreaTaroni86

Yanıtlar:


270

Bunun SELECT COUNT(*) FROM ...yerine bir sorgu yapın .

VEYA

int size =0;
if (rs != null) 
{
  rs.last();    // moves cursor to the last row
  size = rs.getRow(); // get row id 
}

Her iki durumda da, tüm veriler üzerinde döngü yapmanız gerekmez.


8
last () ve getRow (), ResultSet sınıfında statik yöntemler değildir.
JeeBee

70
Kısacası, statik olup olmadıklarına bakılmaksızın, onlar hakkında başkalarına yazarken her zaman bu şekilde yöntemlere atıfta bulunuyorum. Aslında nesnenin bir örneğini oluşturmak ve yöntemi çağırmak gerekir.
laz

51
Daha az karışıklık için SomeClass.staticMethod () ve SomeClass # instanceMethod () yazıyorum.
Jake

9
Bir yürütülürken döndürülen değer nasıl alınır select count?
Naftuli Kay

16
ResultSet#last()her tür ResultSetnesne üzerinde çalışmazsa , ya ResultSet.TYPE_SCROLL_INSENSITIVEda birini kullandığınızdan emin olmanız gerekirResultSet.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
}

5
İf (rs.last ()) kod bloğunun içinde doğru yöntem rs.first () yerine rs.beforeFirst () olmaz mı? Bu şekilde, while döngüsünde işlenmek üzere sonuç kümenizdeki ilk kaydı atlamıyorsunuz.
karlgrz

İmleci önce olarak ayarlamayı unutmaİf bloğunun dışında bir ilk var mı?
Gobliins

As ResultSet dokümanlar söylüyorlar getRow()çalışır TYPE_FORWARD_ONLYresultsets ve beforeFirst()olanlar için hataları atar. O zaman bu cevap hatalı değil mi?
CodePro_NotYet

5
Bu yalnızca ifade kaydırmaya duyarsız seçenekle oluşturulduğunda çalışır:ps=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
BullyWiiPlaza

19

Eh, bir varsa ResultSetÇeşidi ResultSet.TYPE_FORWARD_ONLYbunu bu şekilde (ve saklamak istediğiniz değil bir geçiş için ResultSet.TYPE_SCROLL_INSENSITIVEveya ResultSet.TYPE_SCROLL_INSENSITIVEkullanıma edebilmek için .last()).

Satır sayısını içeren üstte ilk sahte / sahte bir satır eklediğiniz çok güzel ve verimli bir kesmek öneririm.

Misal

Diyelim ki sorgunuz aşağıdaki

select MYBOOL,MYINT,MYCHAR,MYSMALLINT,MYVARCHAR
from MYTABLE
where ...blahblah...

ve çıktınız şöyle

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]

Kodunuzu aşağıdaki gibi bir şeye yeniden düzenleyin:

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

Sorgu çıktınız artık şöyle bir şey olacak:

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]

Yani sadece

if(rs.next())
    System.out.println("Recordcount: "+rs.getInt("RECORDCOUNT"));//hack: first record contains the record count
while(rs.next())
    //do your stuff

İlginç, ancak dinamik olarak / genel olarak ilk seçme deyimlerini nasıl oluşturabilirsiniz: MYBOOL olarak cast (boole olarak null), vb? Bunun için, "select" deyiminin alanlarının ve boolean, char, int, ect ... gibi veri türlerinin meta verisine ihtiyacınız olacaktır.
user1697575

Bu, tüm alan ayrıntılarına erişiminiz olduğunda yararlıdır ve hız ana endişenizdir (ve bu nedenle hızlı bir şekilde ResultSet.TYPE_FORWARD_ONLY
yapışmanız

11
int i = 0;
while(rs.next()) {
    i++;
}

ResultSet boyutunu hesaplamak için bu yöntemi kullanmanın dezavantajı nedir anlamıyorum. Bu harika ... ekstra bir SQL parametresi kullanmayın. Lütfen bu yöntem hakkında yorum yapın.
Madeyedexter

5
Performans burada anahtar kelimedir. Sonuç kümenizin 100 milyon kayıt olduğunu düşünün, o zaman sorunu göreceksiniz
Pierre

7
Önceden aynı boyutta bir dizi yapmak gerekiyor çünkü sonuçları işlemeden önce sonuç kümesi boyutunu bilmek istiyorum. Diğer yanıtlarda belirtildiği gibi, tüm satırları iki kez taramak her zaman işe yaramaz.
Ivo

11

Kullanırken bir istisna var rs.last()

if(rs.last()){
    rowCount = rs.getRow(); 
    rs.beforeFirst();
}

:

java.sql.SQLException: Invalid operation for forward only resultset

bunun nedeni varsayılan olarak ResultSet.TYPE_FORWARD_ONLY, yani yalnızcars.next()

çözüm şudur:

stmt=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
    ResultSet.CONCUR_READ_ONLY); 

12
Geçiş ResultSet.TYPE_FORWARD_ONLYiçin ResultSet.TYPE_SCROLL_INSENSITIVEgenellikle katlandığı büyük performans cezası.
Unai Vivi

3
Masamda test ettim (10 sütun, 187 392 satır). Testim sorgulayıp tüm öğeleri dizeye yükledi. TYPE_FORWARD_ONLY için yaklaşık 1 saniye sürdü. TYPE_SCROLL_INSENSITIVE için yaklaşık 7 saniye sürdü. Daha doğrusu kullanıldığında SELECT COUNT(*) FROM default_tblönce SELECT COUNT(*) FROM default_tblbunun tamamen az 1.5 saniyeden daha sürdü. Gömülü derbi veritabanında test ettim 10.11.1.1
Vit Bernatik

4

ResultSet'in boyutunu alma yolu, ArrayList'i kullanmaya gerek yok vb.

int size =0;  
if (rs != null)   
{  
rs.beforeFirst();  
 rs.last();  
size = rs.getRow();
}

Şimdi boyut alacaksınız ve ResultSet'i yazdırmak istiyorsanız, yazdırmadan önce aşağıdaki kod satırını da kullanın,

rs.beforeFirst();  

4

[Hız değerlendirmesi]

Ppl Lot burada da anlaşılacağı ResultSet.last()ama açık bağlantı gerekir bunun için ResultSet.TYPE_SCROLL_INSENSITIVEDerby gömülü veritabanı için 10 kata kadar olan YAVAŞ daha ResultSet.TYPE_FORWARD_ONLY.

Gömülü Derby ve H2 veritabanları için yapılan mikro testlerime göre SELECT'inizden SELECT COUNT(*)önce aramak çok daha hızlı .

Kodum ve karşılaştırmalı değerlendirmelerim


3

Satır sayımı yapmanın basit bir yoludur.

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

4
Evet, işe yarıyor. Ama bence OP aslında onları işlemeden önce satır sayısını bilmekte zorlanıyor . Gerçek hayat nedenleri şu ana kadar bu konuyla mücadele etmek zorundayım: 1.) kayıt satırlarının sayfalanması 2.) uzun vadeli görevlerde ilerleme izleme amaçları için işlenen satırların gösterilmesi ...
ppeterka

Önceden yerleştirilmiş veri yapısı boyutu başka bir nedendir. Ben sadece tek bir değer olduğunda libs bol 10 eleman Listeleri döndürdüğünü gördüm çünkü geliştiricilerin ResultSet ile aynı sorunu vardı.
Joseph Lust

2
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);

1

ResultSet arabiriminin çalışma zamanı değerini kontrol ettim ve hemen hemen her zaman bir ResultSetImpl olduğunu öğrendim . ResultSetImpl, getUpdateCount()aradığınız değeri döndüren adlı bir yönteme sahiptir .

Bu kod örneği yeterli olmalıdır:
ResultSet resultSet = executeQuery(sqlQuery);
double rowCount = ((ResultSetImpl)resultSet).getUpdateCount()

Ben downcasting genellikle güvensiz bir prosedür olduğunu biliyorum ama bu yöntem henüz başarısız olmadı.


2
Tomcat / MySQL ile çalışmıyor:java.lang.ClassCastException: org.apache.tomcat.dbcp.dbcp.DelegatingResultSet cannot be cast to com.mysql.jdbc.ResultSetImpl
Panu Haaramo

1

Bugün, bu mantığı neden RS sayımını bilmediğimi kullandım.

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.

0
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();

0

Aynı sorunu yaşıyordum. ResultSet.first()İcra çözüldükten hemen sonra bu şekilde kullanmak :

if(rs.first()){
    // Do your job
} else {
    // No rows take some actions
}

Dokümantasyon ( link ):

boolean first()
    throws SQLException

İmleci bu ResultSetnesnenin ilk satırına taşır .

İadeler:

trueimleç geçerli bir satırdaysa; falsesonuç kümesinde hiç satır yoksa

atar:

SQLException- bir veritabanı erişim hatası oluşursa; bu yöntem kapalı bir sonuç kümesinde çağrılır veya sonuç kümesi türüTYPE_FORWARD_ONLY

SQLFeatureNotSupportedException - JDBC sürücüsü bu yöntemi desteklemiyorsa

Dan beri:

1.2


0

En kolay yaklaşım olan Run Count (*) sorgusu, sonuç satırını almak için sonuçSet.next () yapın ve ardından sayıyı almak için sonuçSet.getString (1) öğesini yapın. Kod:

ResultSet rs = statement.executeQuery("Select Count(*) from your_db");
if(rs.next()) {
   int count = rs.getString(1).toInt()
}

-1

Sütuna bir ad verin ..

String query = "SELECT COUNT(*) as count FROM

Bu sütunu ResultSet nesnesinden int'e referansla ve mantığınızı oradan yapın ..

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.");
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.