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.