java.sql.ResultSet의 크기는 어떻게 얻습니까?


285

이것은 매우 간단한 작업이 아니어야합니까? 그러나 나는 방법 size()도 없습니다 length().


11
나는 그 생략의 이유를 알고 싶습니다.
— Slamice

이 질문에 대한 나의 이해는 튜플 수가 아닌 ResultSet IN BYTES의 크기를 찾고 싶다는 것입니다.
— DejanLekic

프로세스 데이터 전에 올바른 차원을 갖지 않는 것은 매우 성가 시지만 배열에 저장 해야하는 경우 List와 같은 데이터 구조를 사용하고 toArray () 메서드를 사용하여 배열로 변환하는 것을 고려할 수 있습니다.
— AndreaTaroni86

답변:


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
last () 및 getRow ()는 ResultSet 클래스의 정적 메소드가 아닙니다.
— JeeBee

70
간결하게하기 위해, 나는 정적이든 아니든 상관없이 항상 다른 방식으로 메소드를 작성할 때 이러한 방식으로 메소드를 참조합니다. 실제로 객체의 인스턴스를 생성하고 메소드를 호출하는 것은 내포되어 있습니다.
— laz

51
혼란을 줄이기 위해 SomeClass.staticMethod () 및 SomeClass # instanceMethod ()를 작성합니다.
— Jake

9
select count?를 실행할 때 반환되는 값을 어떻게 가져 옵니까 ?
— Naftuli Kay

16
ResultSet#last()수행은하지의 모든 유형에 대한 작업 ResultSet개체를, 당신은 당신이 중 하나를 사용해야 ResultSet.TYPE_SCROLL_INSENSITIVE또는ResultSet.TYPE_SCROLL_SENSITIVE
— 마리우스 이온

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
if (rs.last ()) 코드 블록 내에서 올바른 메소드가 rs.first () 대신 rs.beforeFirst ()가 아니겠습니까? 이런 식으로 while 루프에서 처리하기 위해 결과 세트의 첫 번째 레코드를 건너 뛰지 않습니다.
— karlgrz

if 블록 밖에서 커서를 beforeFirst로 다시 설정하는 것을 잊지 마십시오.
— Gobliins

으로 의 ResultSet 문서는 말을 getRow()작동 TYPE_FORWARD_ONLYResultSet를, 그리고 beforeFirst()사람들을 위해 오류가 발생합니다. 이 대답이 잘못이 아닙니까?
— CodePro_NotYet

5
이것은 스크롤 비 ps=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
— 감지

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

흥미롭지 만 어떻게 동적으로 / 일반적으로 첫 번째 select 문을 생성하겠습니까 : cast (null as boolean) as MYBOOL 등 이를 위해서는 부울, char, int, 요법 등과 같은 "select"문의 필드 및 데이터 유형에 대한 메타 데이터가 필요합니다.이 메타 데이터는 모든 이점을 무효화하는 추가 DB 트립이 필요할 수 있습니다.
— user1697575

이것은 모든 분야의 세부 사항에 접근 할 수 있고 속도가 주요 관심사 인 경우에 유용합니다 (따라서 단식해야합니다 ResultSet.TYPE_FORWARD_ONLY)
— Unai Vivi

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

이 방법을 사용하여 ResultSet 크기를 계산할 때의 단점을 이해하지 못합니다. 추가 SQL 매개 변수를 사용하지 않는 것이 좋습니다. 이 방법에 대해 의견을 말하십시오.
— Madeyedexter

5
성능은 키워드입니다. 상상해 당신의 결과 집합은 다음 문제를 볼 100M 기록입니다
— 피에르

7
미리 같은 크기의 배열을 만들어야하기 때문에 결과를 처리하기 전에 결과 세트 크기를 알고 싶습니다. 다른 답변에서 언급했듯이 모든 행을 두 번 스캔하는 것이 항상 작동하지는 않습니다.
— Ivo

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일반적으로 성능 이 크게 저하됩니다.
— Unai Vivi

3
내 테이블 (10 열, 187 392 행)에서 테스트했습니다. 내 테스트는 모든 요소를 ​​쿼리하고 문자열로로드했습니다. TYPE_FORWARD_ONLY의 경우 약 1 초가 걸렸습니다. TYPE_SCROLL_INSENSITIVE의 경우 약 7 초가 걸렸습니다. 내가 SELECT COUNT(*) FROM default_tbl전에 사용했을 때 SELECT COUNT(*) FROM default_tbl1.5 초 미만이 걸렸습니다. 나는 임베디드 Derby 데이터베이스 10.11.1.1 테스트
— 비타 Bernatik에게

4

ResultSet의 크기를 얻는 방법, ArrayList 등을 사용할 필요가 없음

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

이제 크기가 생깁니다. 결과 집합을 인쇄하려면 다음 코드 줄을 사용하여 인쇄하십시오.

rs.beforeFirst();  

4

[속도 고려]

여기에 많은 ppl이 제안 ResultSet.last()하지만 ResultSet.TYPE_SCROLL_INSENSITIVEDerby 내장 데이터베이스의 경우 최대 10 배 보다 느리 므로 연결을 열어야합니다.ResultSet.TYPE_FORWARD_ONLY .

임베디드 Derby 및 H2 데이터베이스에 대한 나의 마이크로 테스트에 따르면 SELECT COUNT(*)SELECT 전에 호출하는 것이 훨씬 빠릅니다 .

여기 내 코드와 벤치 마크에 대한 자세한 내용이 있습니다.


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
예, 잘 작동합니다. 그러나 OP는 실제로 행 을 처리 하기 전에 행 수를 아는 데 어려움을 겪고 있다고 생각 합니다. 실생활의 이유 나는 지금까지이 문제와 싸워야했다. 1.) 레코드 행 페이징 2.) 진행 상황 모니터링 목적으로 장기 실행 작업에서 처리 된 행 표시 ...
— ppeterka

사전 할당 데이터 구조 크기가 또 다른 이유입니다. 개발자가 ResultSet에 동일한 문제가 있었기 때문에 단일 값이있을 때 많은 lib가 10 요소 목록을 반환하는 것을 보았습니다.
— 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 인터페이스 의 런타임 값을 확인하고 거의 항상 ResultSetImpl 이라는 것을 알았습니다 . ResultSetImpl에는 getUpdateCount()찾고자하는 값을 리턴 하는 메소드 가 있습니다.

이 코드 샘플은 다음과 같이 충분합니다.
ResultSet resultSet = executeQuery(sqlQuery);
double rowCount = ((ResultSetImpl)resultSet).getUpdateCount()

다운 캐스팅은 일반적으로 안전하지 않은 절차이지만이 방법으로 아직 실패하지는 않았습니다.


2
Tomcat / MySQL과 함께 작동하지 않음 :java.lang.ClassCastException: org.apache.tomcat.dbcp.dbcp.DelegatingResultSet cannot be cast to com.mysql.jdbc.ResultSetImpl
— Panu Haaramo

1

오늘 나는이 논리를 사용하여 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.

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

가장 쉬운 방법 인 Run Count (*) 쿼리는 resultSet.next ()를 수행하여 첫 번째 행을 가리킨 다음 resultSet.getString (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

ResultSet 객체의 열을 int로 참조하고 거기에서 논리를 수행하십시오.

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.");
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.