मुझे java.sql.ResultSet का आकार कैसे मिलेगा?


284

यह एक बहुत सीधा ऑपरेशन नहीं होना चाहिए? हालाँकि, मैं देख रहा हूँ कि न तो कोई विधि है size()और न ही कोई length()विधि।


11
मुझे उस चूक का कारण जानना अच्छा लगेगा।
स्लैमिस

प्रश्न के बारे में मेरी समझ यह थी कि आप BYTES में परिणाम के आकार को खोजना चाहते हैं, न कि
टुपल्स की

प्रक्रिया डेटा से पहले सही आयाम न होना बहुत कष्टप्रद है, लेकिन यदि आपको उन्हें किसी सरणी में संग्रहीत करना है, तो आप सूची जैसी डेटा संरचना का उपयोग करने पर विचार कर सकते हैं और फिर उन्हें सरणी () पद्धति से सरणी में परिवर्तित कर सकते हैं।
एंड्रियाटोनी 86

जवाबों:


270

SELECT COUNT(*) FROM ...इसके बजाय एक क्वेरी करें ।

या

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

किसी भी मामले में, आपको पूरे डेटा पर लूप नहीं करना पड़ेगा।


8
अंतिम () और getRow () ResultSet वर्ग में स्थिर तरीके नहीं हैं।
JeeBee

70
संक्षिप्तता के लिए मैं हमेशा इस तरीके से संदर्भ देता हूं जब उनके बारे में दूसरों को लिखते हैं, भले ही वे स्थिर हों या न हों। वास्तव में वस्तु का एक उदाहरण बनाना और विधि को कॉल करना निहित है।
laz

51
मैं कम भ्रम के लिए SomeClass.staticMethod () और SomeClass # instMethod () लिखता हूं।
जेक

9
किसी को निष्पादित करते समय एक मूल्य कैसे प्राप्त होता है select count?
नातुल्ली काय

16
ResultSet#last()सभी प्रकार की ResultSetवस्तुओं पर काम नहीं करता है , आपको यह सुनिश्चित करने की ज़रूरत है कि आप एक का उपयोग करें ResultSet.TYPE_SCROLL_INSENSITIVEया तोResultSet.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
अगर (rs.last ()) कोड ब्लॉक के अंदर, rs.beforeFirst () rs.first () के बजाय सही विधि नहीं होगी? इस तरह, आप लूप में प्रसंस्करण के लिए सेट किए गए अपने परिणाम में पहला रिकॉर्ड नहीं छोड़ रहे हैं।
कार्लगज़

क्या आप ब्लॉक से पहले कर्सर को पहले सेट करना नहीं भूलते हैं?
गोबलींस

जैसा कि ResultSet डॉक्स कहता है, ResultSets के getRow()लिए काम करता है TYPE_FORWARD_ONLY, और beforeFirst()उन लोगों के लिए त्रुटियों को फेंकता है। क्या यह उत्तर दोषपूर्ण नहीं है?
CodePro_NotYet

5
यह केवल तब काम करता है जब स्टेटमेंट को स्क्रॉल असंवेदनशील विकल्प के साथ बनाया जाता है:ps=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
BullyWiiPlaza

19

ठीक है, यदि आपके पास एक ResultSetप्रकार है , तो आप ResultSet.TYPE_FORWARD_ONLYइसे उसी तरह रखना चाहते हैं (और उपयोग करने में सक्षम होने के लिए स्विच करने के लिए या नहीं )।ResultSet.TYPE_SCROLL_INSENSITIVEResultSet.TYPE_SCROLL_INSENSITIVE.last()

मैं एक बहुत अच्छी और कुशल हैक का सुझाव देता हूं, जहां आप शीर्ष पर पहली बोगस / फोनी पंक्ति जोड़ते हैं जिसमें पंक्तियों की संख्या होती है।

उदाहरण

मान लें कि आपकी क्वेरी निम्नलिखित है

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

और आपका आउटपुट जैसा दिखता है

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]

बस अपने कोड को कुछ इस तरह से रिफलेक्टर करें:

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

आपका क्वेरी आउटपुट अब कुछ इस तरह का होगा

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]

तो आपको बस करना है

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

दिलचस्प है, लेकिन आप गतिशील रूप से / उदारतापूर्वक पहले चुनिंदा बयान कैसे उत्पन्न करेंगे: कास्ट (बूलियन के रूप में शून्य) MYBOOL, ect के रूप में? उसके लिए आपको "सेलेक्ट" स्टेटमेंट के क्षेत्र और डेटाटाइप्स जैसे कि बूलियन, चार, इंट, एक्ट ...) के मेटाडेटा की आवश्यकता होगी, जिसमें अतिरिक्त डीबी यात्रा की आवश्यकता हो सकती है जो सभी लाभों को नकार देगा।
14:16 पर user1697575

यह तब उपयोगी होता है जब आपके पास सभी फ़ील्ड विवरणों तक पहुंच होती है और गति आपकी मुख्य चिंता होती है (और इसलिए एक तेजी से छड़ी करने की आवश्यकता होती है ResultSet.TYPE_FORWARD_ONLY)
उनाई विवि

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

मुझे समझ में नहीं आ रहा है कि ResultSet आकार की गणना करने के लिए इस पद्धति का उपयोग करने का दोष क्या है। यह बहुत अच्छा है ... एक अतिरिक्त SQL पैरामीटर का कोई उपयोग नहीं। कृपया इस विधि पर टिप्पणी करें।
Madeyedexter

5
प्रदर्शन यहाँ खोजशब्द है। कल्पना करें कि आपका परिणाम 100 मीटर रिकॉर्ड है तब आप इस मुद्दे को देखेंगे
पियरे

7
मैं परिणाम सेट करने का परिणाम जानना चाहता हूं क्योंकि मैं पहले से ही उसी आकार की एक सरणी बनाने के लिए परिणामों की प्रक्रिया कर रहा हूं। और, जैसा कि अन्य उत्तरों में कहा गया है, सभी पंक्तियों को दो बार स्कैन करना हमेशा काम नहीं करेगा।
इवो

11

उपयोग करते समय मुझे एक अपवाद मिला rs.last()

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

:

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

यह डिफ़ॉल्ट रूप से होने के कारण है ResultSet.TYPE_FORWARD_ONLY, जिसका अर्थ है कि आप केवल उपयोग कर सकते हैंrs.next()

समाधान है:

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

12
से स्विच कर रहे ResultSet.TYPE_FORWARD_ONLYकरने के लिए ResultSet.TYPE_SCROLL_INSENSITIVEआम तौर पर एक में पड़ता है विशाल प्रदर्शन की सजा।
उनाई विवि

3
मैंने इसे अपनी तालिका (10 कॉलम, 187 392 पंक्तियों) पर परीक्षण किया। मेरे परीक्षण ने सभी तत्वों को क्वेरी और लोड किया। TYPE_FORWARD_ONLY के लिए लगभग 1 सेकंड का समय लगा। TYPE_SCROLL_INSENSITIVE के लिए इसने लगभग 7 सेकंड का समय लिया। जब मैंने इसके बजाय SELECT COUNT(*) FROM default_tblपहले SELECT COUNT(*) FROM default_tblइसका इस्तेमाल किया तो यह पूरी तरह से 1.5 सेकंड से भी कम समय लगा। मैंने एम्बेडेड डर्बी डेटाबेस 10.11.1.1
वीट बर्नैटिक

4

ResultSet का आकार प्राप्त करने का तरीका, ArrayList आदि का उपयोग करने की कोई आवश्यकता नहीं है

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

अब आपको आकार मिलेगा, और यदि आप कोड का निम्नलिखित लाइन का उपयोग प्रिंट करने से पहले ResultSet प्रिंट करना चाहते हैं,

rs.beforeFirst();  

4

[गति पर विचार]

Ppl के बहुत यहाँ पता चलता है ResultSet.last(), लेकिन उस के लिए आप एक के रूप में खुले कनेक्शन की आवश्यकता होगी ResultSet.TYPE_SCROLL_INSENSITIVEजो डर्बी के लिए एम्बेडेड डेटाबेस में 10 गुना पर निर्भर है धीमी सेResultSet.TYPE_FORWARD_ONLY

एम्बेडेड डर्बी और एच 2 डेटाबेस के लिए मेरे सूक्ष्म परीक्षणों के अनुसार SELECT COUNT(*)आपके सेलेक्ट से पहले कॉल करना काफी तेज है ।

यहाँ मेरा कोड और मेरे बेंचमार्क अधिक विस्तार से हैं


3

यह पंक्तियों की गिनती करने का एक सरल तरीका है।

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
हाँ, यह काम करता है। लेकिन मुझे लगता है कि ओपी वास्तव में उन्हें संसाधित करने से पहले पंक्तियों की संख्या जानने के साथ संघर्ष करता है। वास्तविक जीवन के कारणों से मुझे इस मुद्दे पर अब तक लड़ना होगा: 1.) रिकॉर्ड पंक्तियों का पेजिंग 2.) प्रगति की निगरानी के उद्देश्यों के लिए लंबे समय तक चलने वाले कार्यों में संसाधित पंक्तियों को दिखाना ...
ppeterka

Preallocating डेटा संरचना का आकार एक और कारण हैं। मैंने देखा है कि 10 तत्वों की वापसी के लिए बहुत सारे लिबास हैं जब केवल एक ही मूल्य है क्योंकि देव का ResultSet के साथ यही मुद्दा था।
जोसेफ वासना

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 इंटरफ़ेस के रनटाइम मान की जाँच की और पाया कि यह हर समय एक ResultSetImpl बहुत अधिक था । ResultSetImpl में एक विधि होती है, जिसे getUpdateCount()वह मान दिया जाता है जिसे आप खोज रहे हैं।

यह कोड नमूना पर्याप्त होना चाहिए:
ResultSet resultSet = executeQuery(sqlQuery);
double rowCount = ((ResultSetImpl)resultSet).getUpdateCount()

मुझे लगता है कि डाउनकास्टिंग आम तौर पर एक असुरक्षित प्रक्रिया है लेकिन यह तरीका अभी तक मुझे विफल नहीं हुआ है।


2
java.lang.ClassCastException: org.apache.tomcat.dbcp.dbcp.DelegatingResultSet cannot be cast to com.mysql.jdbc.ResultSetImpl
टॉमकैट

1

आज, मैंने इस तर्क का उपयोग किया कि मुझे आरएस की गिनती क्यों नहीं आती।

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

मुझे भी यही समस्या आ रही थी। ResultSet.first()निष्पादन के हल के बाद इस तरह से उपयोग करना :

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

प्रलेखन ( लिंक ):

boolean first()
    throws SQLException

इस ResultSetऑब्जेक्ट में कर्सर को पहली पंक्ति में ले जाता है।

यह दिखाता है:

trueयदि कर्सर एक वैध पंक्ति पर है; falseयदि परिणाम सेट में कोई पंक्तियाँ नहीं हैं

फेंकता:

SQLException- अगर डेटाबेस एक्सेस एरर होता है; इस विधि को बंद परिणाम सेट पर या परिणाम सेट प्रकार कहा जाता हैTYPE_FORWARD_ONLY

SQLFeatureNotSupportedException - अगर JDBC ड्राइवर इस विधि का समर्थन नहीं करता है

जबसे:

1.2


0

सबसे आसान तरीका, रन काउंट (*) क्वेरी, परिणामी करें। फिर भी (पहली पंक्ति को इंगित करने के लिए) और फिर परिणाम प्राप्त करने के लिए बस परिणाम देखें। (1)। कोड:

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

-1

कॉलम को एक नाम दें ।।

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

उस कॉलम को रिजल्टसेट ऑब्जेक्ट से एक इंट में संदर्भ दें और वहां से अपना तर्क दें।

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.");
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.