Java ResultSet วิธีตรวจสอบว่ามีผลลัพธ์ใด ๆ หรือไม่


311

Resultsetไม่มีเมธอดสำหรับ hasNext ฉันต้องการตรวจสอบว่า resultSet มีค่าใด ๆ หรือไม่

นี้เป็นวิธีที่ถูกต้องหรือไม่

if (!resultSet.next() ) {
    System.out.println("no data");
} 

2
สำหรับผู้อ่านในอนาคตเช่นฉัน: คำตอบที่ช่วยฉันคือคนที่มาจาก Felype และ Dermot Doherty
Benj

คำตอบ:


237

นั่นเป็นที่ถูกต้องต้นResultSetของเคอร์เซอร์จะชี้ไปก่อนแถวแรกถ้าสายแรกที่next()ผลตอบแทนแล้วก็มีข้อมูลในไม่มีfalseResultSet

หากคุณใช้วิธีนี้คุณอาจต้องโทรbeforeFirst()ทันทีหลังจากรีเซ็ตเนื่องจากมีการวางตำแหน่งตัวเองผ่านแถวแรกตอนนี้

อย่างไรก็ตามควรสังเกตว่าคำตอบของ Seiferด้านล่างเป็นคำตอบที่ดีกว่าสำหรับคำถามนี้


37
แต่โปรดจำไว้ว่าถ้ามี / มี / แถวหลังจากการทดสอบนั้นคุณจะชี้ไปที่แถวแรก ดังนั้นให้แน่ใจว่าคุณไม่ได้ข้ามแถวโดยไม่ตั้งใจ
Matthew Flaschen

1
จุดดีที่เคอร์เซอร์ (ตัวชี้) ชี้ไปที่แถวแรก
JohnMerlino

@ MatthewFlaschen คุณพูดถูกเพื่อแก้ปัญหาการข้ามแถวแรกฉันใช้ do {... } ขณะที่ (rs.next);
อิสราเอล

8
นอกจากนี้คุณยังสามารถโทรisBeforeFirst()เพื่อทดสอบว่ามีแถวใด ๆ ที่ส่งคืนโดยไม่เลื่อนเคอร์เซอร์จากนั้นดำเนินการตามปกติ
SnakeDoc

528

สมมติว่าคุณกำลังทำงานกับกลับมาใหม่ที่มีเคอร์เซอร์ชี้ก่อนแถวแรกเป็นวิธีที่ง่ายต่อการตรวจสอบเรื่องนี้เป็นเพียงการโทรResultSet isBeforeFirst()วิธีนี้จะช่วยให้ไม่ต้องติดตามย้อนกลับหากต้องอ่านข้อมูล

ตามที่อธิบายไว้ในเอกสารประกอบผลตอบแทนนี้เป็นเท็จถ้าเคอร์เซอร์อยู่ไม่ก่อนระเบียนแรกหรือถ้ามีแถวใน ResultSet

if (!resultSet.isBeforeFirst() ) {    
    System.out.println("No data"); 
} 

 


15
ขอบคุณใช่ฉันรู้ แต่ฉันพบปัญหาเดียวกันและไม่พอใจกับการมองไปข้างหน้าเพื่อตรวจสอบแล้วย้อนกลับไปอ่าน ฉันคิดว่าวิธีแก้ปัญหาที่ง่ายกว่านี้จะเป็นประโยชน์ต่อผู้อื่นที่อยู่ในสถานการณ์เดียวกันเช่นกัน
Seifer

5
โปรดทราบว่าอย่างน้อยสำหรับ DB2 ชุดผลลัพธ์จะต้องเป็นชนิด "เลื่อนได้" สามารถตั้งค่านี้เมื่อคุณสร้างคำสั่งที่จะดำเนินการ
Laurence Dougal Myers

1
คำตอบของ Felype ด้านล่างเสร็จสมบูรณ์มากขึ้น
Tom Howard

จากเอกสาร Oracle: หมายเหตุ: การสนับสนุนเมธอด isBeforeFirst นั้นเป็นทางเลือกสำหรับ ResultSets ที่มีประเภทชุดผลลัพธ์เป็น TYPE_FORWARD_ONLY
emi-le

52

คุณสามารถทำสิ่งต่อไปได้เสมอและเพียงแค่ทำการตรวจสอบลูปโพสต์

if (!resultSet.next() ) {
    System.out.println("no data");
} else {

    do {
     //statement(s)
    } while (resultSet.next());
}

21

คุณมักจะทำสิ่งนี้:

while ( resultSet.next() ) { 
   // Read the next item
   resultSet.getString("columnName");
}

หากคุณต้องการรายงานชุดว่างเพิ่มตัวแปรนับรายการที่อ่าน หากคุณต้องการอ่านเพียงรายการเดียวรหัสของคุณก็เพียงพอแล้ว


16

เพื่อให้แน่ใจว่าชุดผลลัพธ์ว่างเปล่าหรือไม่คำนึงถึงตำแหน่งเคอร์เซอร์ฉันจะทำสิ่งนี้:

public static boolean isMyResultSetEmpty(ResultSet rs) throws SQLException {
    return (!rs.isBeforeFirst() && rs.getRow() == 0);
}

ฟังก์ชั่นนี้จะกลับมาจริงถ้า ResultSet ว่างเปล่าเท็จถ้าไม่หรือโยน SQLException ถ้า ResultSet นั้นถูกปิด / ไม่เริ่มต้น


12

ดีที่สุดในการใช้ ResultSet.next () พร้อมกับทำ {... } ในขณะที่ () ไวยากรณ์สำหรับสิ่งนี้

"ตรวจสอบผลลัพธ์ใด ๆ " การเรียก ResultSet.next () เลื่อนเคอร์เซอร์ไปที่แถวแรกดังนั้นใช้ไวยากรณ์ do {... } while () ในการประมวลผลแถวนั้นในขณะที่ดำเนินการกับแถวที่เหลือที่ส่งคืนโดยวนซ้ำ

วิธีนี้คุณจะได้รับการตรวจสอบผลลัพธ์ใด ๆ ในขณะที่ในเวลาเดียวกันก็ประมวลผลผลลัพธ์ที่ส่งคืนด้วยเช่นกัน

if(resultSet.next()) { // Checks for any results and moves cursor to first row,
    do { // Use 'do...while' to process the first row, while continuing to process remaining rows

    } while (resultSet.next());
}

8

ตามคำตอบที่เหมาะสมที่สุดข้อเสนอแนะคือใช้ "isBeforeFirst ()" นั่นไม่ใช่ทางออกที่ดีที่สุดถ้าคุณไม่ได้มี "ไปข้างหน้าเพียงพิมพ์"

มีวิธีการที่เรียกว่า " .first () " น้อยเกินไปที่จะได้รับผลลัพธ์ที่เหมือนกันแน่นอน คุณตรวจสอบว่ามีบางสิ่งใน "resultset" ของคุณและไม่เลื่อนเคอร์เซอร์ของคุณ

เอกสารประกอบระบุว่า: "(... ) false หากไม่มีแถวในชุดผลลัพธ์ "

if(rs.first()){
    //do stuff      
}

นอกจากนี้คุณยังสามารถเรียก isBeforeFirst () เพื่อทดสอบว่ามีแถวใด ๆ ที่ส่งคืนโดยไม่เลื่อนเคอร์เซอร์ไปก่อนแล้วดำเนินการตามปกติ - SnakeDoc 2 ก.ย. 57 เวลา 19:00 น

อย่างไรก็ตามมีความแตกต่างระหว่าง "isBeforeFirst ()" และ "first ()" ขั้นแรกสร้างข้อยกเว้นหากทำบน resultset จากประเภท "ส่งต่อเท่านั้น"

เปรียบเทียบสองส่วนการโยน: http://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html#isBeforeFirst () http://docs.oracle.com/javase/7/docs /api/java/sql/ResultSet.html#first ()

ตกลงโดยทั่วไปนี่หมายความว่าคุณควรใช้ "isBeforeFirst" ตราบใดที่คุณมีประเภท "ส่งต่อเท่านั้น" มิฉะนั้นจะมีค่าใช้จ่ายมากเกินไปที่จะใช้ "first ()"


1
"overkill น้อยลง" เพื่อให้ได้ผลลัพธ์เดียวกันแน่นอนอย่างไร ดูเหมือนว่าฉันวัตถุประสงค์แรก () คือการเลื่อนเคอร์เซอร์ไปที่แถวแรกหากยังไม่ได้มี (และกลับจริงถ้ามันประสบความสำเร็จ) isBeforeFirst เป็นฟังก์ชั่นการวินิจฉัยอย่างหมดจดเท่านั้นและดูเหมือนว่าเหมาะกับวัตถุประสงค์ของผู้เขียน นอกจากนี้วิธีแรก () ถูกใช้คำมันจะส่งกลับจริงตราบใดที่มัน "ในแถวที่ถูกต้อง" ... ซึ่งแปลกที่ใครจะคิดว่ามันจะถูกเรียกว่า "ในแถวแรก" สำหรับฉันฉันไม่เห็นข้อได้เปรียบของการใช้ first () ในสถานการณ์นี้เว้นแต่เคอร์เซอร์ของคุณมีระดับสูงและคุณต้องการนำมันกลับไปที่จุดเริ่มต้น
Jon

5

หากคุณต้องการดูว่ามีแถวใด ๆ ในชุดผลลัพธ์ใช่หรือไม่

โปรดทราบว่าnext()จะย้ายไปยังแถวถัดไปเสมอดังนั้นหากคุณวางแผนที่จะทำการอ่านใด ๆ จากชุดผลลัพธ์คุณต้องคำนึงถึงสิ่งนั้น

การใช้งานปกติพร้อมชุดผลลัพธ์ (เมื่ออ่านง่าย) คือ:

while (resultSet.next())
{
   ... read from the row here ...
}

ซึ่งแน่นอนว่าจะไม่ทำงานอย่างถูกต้องหากคุณเรียกใช้next()หนึ่งครั้งแล้วเพื่อตรวจสอบว่าชุดผลลัพธ์ว่างเปล่าดังนั้นให้ระวัง แม้ว่าจะมีวิธีการ "สำรองข้อมูล" แต่ก็ไม่ได้รับการสนับสนุนสำหรับชุดผลลัพธ์ทุกประเภท


5

นี่เป็นบทความอ่านที่ใช้ง่ายและเชื่อได้ง่าย

        if (res.next()) {
            do {

                // successfully in. do the right things.

            } while (res.next());
        } else {
           // no results back. warn the user.
        }

2
if (!resultSet.isAfterLast() ) {    
System.out.println("No data"); 
} 

isAfterLast() ส่งกลับค่าเท็จสำหรับชุดผลลัพธ์ว่างเปล่า แต่เนื่องจากเคอร์เซอร์อยู่ก่อนแถวแรกอย่างไรก็ตามวิธีนี้ดูเหมือนชัดเจนยิ่งขึ้น


2
if(resultSet.first) {

} else { 
    system.out.println("No raw or resultSet is empty");
}

เพราะถ้า ResultSet ไม่มีผลดิบresultSet.firstจะส่งคืนค่าเท็จ


แต่มันเลื่อนเคอร์เซอร์ไปที่แถวแรกโดยไม่จำเป็นและอาจทำให้สับสนในการใช้งานอ็อบเจ็ก "รีเซ็ต" เพิ่มเติมและอาจทำให้ข้อมูลสูญหาย
Tigran Babajanyan

แม้ว่าสิ่งนี้จะดูดีขึ้น แต่จะไม่สามารถใช้กับชุดผลลัพธ์เคอร์เซอร์ไปข้างหน้าเท่านั้น
eliteproxy

1

สิ่งที่ดีที่สุดที่ต้องทำคือตรวจสอบแถวแรกเพื่อที่ว่าเมื่อคุณตั้งใจจะรับข้อมูลคุณสามารถหลีกเลี่ยงข้อผิดพลาดในการข้ามแถวได้ สิ่งที่ชอบ: if (! resultSet.first ()) {System.out.println ("ไม่มีข้อมูล"); }


1

โดยใช้ resultSet.next () คุณสามารถรับผลลัพธ์ได้อย่างง่ายดายไม่ว่าจะเป็น resultSet ที่มีค่าใด ๆ หรือไม่ก็ตาม

ResultSet resultSet = preparedStatement.executeQuery();
if(resultSet.next())
 //resultSet contain some values
else
 // empty resultSet

อย่าทำซ้ำคำตอบที่มีอยู่
james.garriss


1

ฉันพยายามตั้งค่าแถวปัจจุบันเป็นดัชนีแรก (จัดการกับคีย์หลัก) ฉันจะแนะนำ

if(rs.absolute(1)){
    System.out.println("We have data");
} else {
    System.out.println("No data");
}

เมื่อมีการเติม ResultSet มันจะชี้ไปก่อนแถวแรก เมื่อตั้งค่าเป็นแถวแรก (ระบุโดยrs.absolute(1)) ระบบจะส่งคืนค่า denoting จริงซึ่งวางไว้ที่แถว 1 สำเร็จหรือเป็นเท็จหากไม่มีแถว เราสามารถอนุมานสิ่งนี้กับ

for(int i=1; rs.absolute(i); i++){
    //Code
}

ซึ่งตั้งค่าแถวปัจจุบันเป็นตำแหน่ง i และจะล้มเหลวหากไม่มีแถวอยู่ นี่เป็นเพียงวิธีอื่นในการ

while(rs.next()){
    //Code
}

คำตอบของคุณคืออะไร?
CMedina

1

ฉันสร้างวิธีการต่อไปนี้เพื่อตรวจสอบว่า ResultSet ว่างเปล่าหรือไม่

public static boolean resultSetIsEmpty(ResultSet rs){        
    try {
        // We point the last row
        rs.last();
        int rsRows=rs.getRow(); // get last row number

        if (rsRows == 0) {
            return true;
        }

        // It is necessary to back to top the pointer, so we can see all rows in our ResultSet object.
        rs.beforeFirst();
        return false;
    }catch(SQLException ex){            
        return true;
    }
}

มันสำคัญมากที่จะต้องพิจารณาสิ่งต่อไปนี้:

ต้องตั้งค่าวัตถุCallableStatementเพื่อให้วัตถุ ResultSet สิ้นสุดและกลับไปด้านบน

TYPE_SCROLL_SENSITIVE : วัตถุ ResultSet สามารถเลื่อนที่ส่วนท้ายและกลับไปด้านบน ยิ่งไปกว่านั้นสามารถติดตามการเปลี่ยนแปลงล่าสุด

CONCUR_READ_ONLY : เราสามารถอ่านข้อมูลวัตถุ ResultSet แต่ไม่สามารถอัปเดตได้

CallableStatement proc = dbconex.prepareCall(select, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);

1

ฉันคิดว่าวิธีที่ง่ายที่สุดในการตรวจสอบชุดผลลัพธ์คือผ่านCollectionUtilsภายใต้แพคเกจorg.apache.commons.collections.CollectionUtils

if(CollectionUtils.isNotEmpty(resultList)){
  /**
  * do some stuff
  */
}

การดำเนินการนี้จะตรวจสอบเงื่อนไขว่างเปล่าและชุดผลลัพธ์

สำหรับข้อมูลรายละเอียดเพิ่มเติมคุณสามารถอ้างอิงเอกสารต่อไปนี้ CollectionUtils


1
ResultSet ไม่ใช่คอลเล็กชัน
Joachim Lous

1

ทำไมไม่ใช้ rs.getRow ()

int getRow()
           throws SQLException
Retrieves the current row number. The first row is number 1, the second number 2, and so on.
Note:Support for the getRow method is optional for ResultSets with a result set type of TYPE_FORWARD_ONLY

Returns:
the current row number; 0 if there is no current row
Throws:
SQLException - if a database access error occurs or this method is called on a closed result set
SQLFeatureNotSupportedException - if the JDBC driver does not support this method
Since:
1.2

ให้ฉันตรวจสอบ "if (rs.getRow ()! = 0)" ดูเหมือนว่าจะทำงานได้ดี


0

คุณสามารถทำอะไรเช่นนี้

boolean found = false;

while ( resultSet.next() )
{
    found = true;
    resultSet.getString("column_name");
}

if (!found)
    System.out.println("No Data");

1
WAAAY ซับซ้อนเกินไป
jordaniac89

0
ResultSet rs = rs.executeQuery();
if(rs.next())
{
  rs = rs.executeQuery();
  while(rs.next())
  {
    //do code part
  }
}
else
{
  //else if no result set
}

มันจะดีกว่าที่จะดำเนินการแบบสอบถามเพราะเมื่อเราเรียกif(rs.next()){....}แถวแรกของ ResultSet จะถูกดำเนินการและหลังจากนั้นภายในwhile(rs.next()){....}เราจะได้รับผลจากบรรทัดถัดไป ดังนั้นฉันคิดว่าการประมวลผลข้อความค้นหาอีกครั้งifเป็นตัวเลือกที่ดีกว่า


5
-1 นี่ไม่ใช่ตัวเลือกที่ดีกว่า ทำไมต้องสืบค้นฐานข้อมูลสองครั้ง ถ้าข้อมูลมีการเปลี่ยนแปลงอย่างมากระหว่างการโทร นี่มันสิ้นเปลือง
Toby Caulk

-2

ในขั้นต้นวัตถุชุดผลลัพธ์ (rs) ชี้ไปที่ BFR (ก่อนบันทึกแรก) เมื่อเราใช้ rs.next () เคอร์เซอร์จะชี้ไปที่ระเบียนแรกและ rs ถือเป็น "true" การใช้ห่วงลูปในขณะที่คุณสามารถพิมพ์ระเบียนทั้งหมดของตาราง หลังจากที่เรียกระเบียนทั้งหมดแล้วเคอร์เซอร์จะย้ายไปที่ ALR (หลังจากบันทึกล่าสุด) และจะถูกตั้งค่าเป็น null ขอให้เราพิจารณาว่ามี 2 บันทึกในตาราง

if(rs.next()==false){
    // there are no records found
    }    

while (rs.next()==true){
    // print all the records of the table
    }

ในมือสั้น ๆ เราสามารถเขียนเงื่อนไขในขณะที่ (rs.next ())


3
วงวนของคุณในขณะนั้นจะไม่ได้รับโอกาสให้ทำงานในแถวแรกที่ส่งคืนซึ่งดูเหมือนว่าจะเป็นข้อบกพร่องที่ร้ายแรงสำหรับวิธีนี้ มีคำแนะนำมากมายที่ดีกว่าอันนี้
จูลส์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.