web-dev-qa-db-ja.com

JavaでResultSetを使用して行数を取得する方法は?

パラメーターとしてResultSetを受け取り、ResultSetの行カウントを含むintを返す単純なメソッドを作成しようとしています。これはこれを行う有効な方法ですか?

int size = 0;
    try {
        while(rs.next()){
            size++;
        }
    }
    catch(Exception ex) {
        System.out.println("------------------Tablerize.getRowCount-----------------");
        System.out.println("Cannot get resultSet row count: " + ex);
        System.out.println("--------------------------------------------------------");
    }

私はこれを試しました:

int size = 0;
try {
    resultSet.last();
    size = resultSet.getRow();
    resultSet.beforeFirst();
}
catch(Exception ex) {
    return 0;
}
return size;

しかし、com.Microsoft.sqlserver.jdbc.SQLServerException: The requested operation is not supported on forward only result sets.というエラーが発生しました

事前にポインタをありがとう!

63
user818700

この結果セットを作成する準備済みステートメントにアクセスできる場合は、次を使用できます。

connection.prepareStatement(sql, 
  ResultSet.TYPE_SCROLL_INSENSITIVE, 
  ResultSet.CONCUR_READ_ONLY);

これにより、カーソルを巻き戻すことができるようにステートメントが準備されます。これは ResultSet Javadoc にも記載されています。

ただし、一般に、大きな結果セットの場合、カーソルの転送と巻き戻しは非常に効率が悪い場合があります。 SQL Serverの別のオプションは、SQLステートメント内の行の総数を直接計算することです。

SELECT my_table.*, count(*) over () total_rows
FROM my_table
WHERE ...
56
Lukas Eder

あなたのSQLステートメント作成コードは

statement = connection.createStatement();

「com.Microsoft.sqlserver.jdbc.SQLServerException:要求された操作は前方のみの結果セットではサポートされていません」を解決するには

statement = connection.createStatement(
    ResultSet.TYPE_SCROLL_INSENSITIVE, 
    ResultSet.CONCUR_READ_ONLY);

上記の変更後、使用できます

int size = 0;
try {
    resultSet.last();
    size = resultSet.getRow();
    resultSet.beforeFirst();
}
catch(Exception ex) {
    return 0;
}
return size;

行数を取得する

33
Fathah Rehman P
Statement s = cd.createStatement();
ResultSet r = s.executeQuery("SELECT COUNT(*) AS rowcount FROM FieldMaster");
r.next();
int count = r.getInt("rowcount");
r.close();
System.out.println("MyTable has " + count + " row(s).");

JDBCは次のメソッドをサポートしていない場合があり、「TYPE_FORWARD_ONLY」などのエラーがこのソリューションを使用します

SqliteはJDBCではサポートしていません。

resultSet.last();
size = resultSet.getRow();
resultSet.beforeFirst();

そのため、この時点でこのソリューションを使用してください。

ありがとう。

20
Java Man

代わりにSELECT COUNT(*) FROM ...クエリを実行します。

ゲッターメソッドを作成しました。

public int getNumberRows(){
    try{
       statement = connection.creatStatement();
       resultset = statement.executeQuery("your query here");
       if(resultset.last()){
          return resultset.getRow();
       } else {
           return 0; //just cus I like to always do some kinda else statement.
       }
    } catch (Exception e){
       System.out.println("Error getting row count");
       e.printStackTrace();
    }
    return 0;
}
5
The01Guy

テーブルがあり、IDをプライマリおよび自動インクリメントとして保存している場合、これは機能します

合計行数を取得するサンプルコード http://www.Java2s.com/Tutorial/Java/0340__Database/GettheNumberofRowsinaDatabaseTable.htm

以下はコードです

import Java.sql.Connection;
import Java.sql.DriverManager;
import Java.sql.ResultSet;
import Java.sql.ResultSetMetaData;
import Java.sql.Statement;

public class Main {
  public static void main(String[] args) throws Exception {
    Connection conn = getConnection();
    Statement st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
        ResultSet.CONCUR_UPDATABLE);

    st.executeUpdate("create table survey (id int,name varchar(30));");
    st.executeUpdate("insert into survey (id,name ) values (1,'nameValue')");
    st.executeUpdate("insert into survey (id,name ) values (2,null)");
    st.executeUpdate("insert into survey (id,name ) values (3,'Tom')");
    st = conn.createStatement();
    ResultSet rs = st.executeQuery("SELECT * FROM survey");

    rs = st.executeQuery("SELECT COUNT(*) FROM survey");
    // get the number of rows from the result set
    rs.next();
    int rowCount = rs.getInt(1);
    System.out.println(rowCount);

    rs.close();
    st.close();
    conn.close();

  }

  private static Connection getConnection() throws Exception {
    Class.forName("org.hsqldb.jdbcDriver");
    String url = "jdbc:hsqldb:mem:data/tutorial";

    return DriverManager.getConnection(url, "sa", "");
  }
}
3
anand

他の人はすでにあなたの問題を解決する方法に答えているので、私はすでに言われたことを繰り返すことはありませんが、私はこれを言います:おそらく、あなたはおそらくあなたが読む前に結果セットの数を知らずにあなたの問題を解決する方法を見つけ出すべきです結果。

特にJavaのような言語では、結果セットを読み取る前に実際に行カウントが必要になる状況はほとんどありません。行カウントが必要になると思う唯一のケースは、行カウントが必要な唯一のデータである場合です(この場合、カウントクエリが優れています)。それ以外の場合は、ラッパーオブジェクトを使用してテーブルデータを表し、これらのオブジェクトをArrayListなどの動的コンテナーに格納する方が適切です。その後、結果セットが繰り返し処理されると、配列リストのカウントを取得できます。結果セットを読み取る前に行数を知る必要があるすべてのソリューションについて、多くの労力をかけずに読み取る前に行数を知らなくてもそうするソリューションを考えることができます。処理する前に行数を知る必要性をバイパスするソリューションを考えることで、ResultSetを保存して、結果セットの最後までスクロールしてから最初に戻るという手間を省きます(大きな結果セットでは非常にコストのかかる操作になる可能性があります) 。

もちろん、結果セットを読み取る前に行カウントが必要になる状況は決してないということではありません。ほとんどの場合、読む前に結果セットのカウントが必要であると人々が考える場合、おそらく必要ではないと言います。別の方法があるかどうかを考えるのに5分かかる価値があります。

トピックに関する私の2セントを提供したかっただけです。

2
aeskreis

関数はResultSetのサイズを返しますが、カーソルは最後のレコードの後に​​設定されるため、beforeFirst()、first()、またはprevious()を呼び出して巻き戻すことなく、行を読み取って巻き戻すことはできません。メソッドは、結果セットを前方のみで使用することはできません(2番目のコードフラグメントと同じ例外が発生します)。

2
socha23

ほとんどのドライバーは前方のみの結果セットをサポートしているため、last、beforeFirstなどのメソッドはサポートされていません。

同じループでデータも取得している場合は、最初のアプローチが適しています。それ以外の場合、resultSetは既に反復されており、再び使用することはできません。

ほとんどの場合、要件は、行をフェッチせずにクエリが返す行数を取得することです。結果セットを反復して行カウントを見つけることは、データを処理することとほぼ同じです。代わりに別のcount(*)クエリを実行することをお勧めします。

2
gkamal

ResultSetには、提供されるオプションに応じてカーソルを前後に移動するメソッドがあります。デフォルトでは、前方に移動します(TYPE_FORWARD_ONLY結果セットタイプ)。結果セットのスクロール可能性と更新を適切に示す定数がない限り、エラーが発生する可能性があります。例えば。 beforeLast()結果セットに行が含まれていない場合、このメソッドは効果がありません。 TYPE_FORWARD_ONLYでない場合はエラーをスローします。

空の行がフェッチされたかどうかを確認する最良の方法---存在しないことを確認した後に新しいレコードを挿入するだけ

if( rs.next() ){

   Do nothing
} else {
  No records fetched!
}

こちら をご覧ください

1
Yergalem

配列をインスタンス化するためにカウントを取得するのを避け、代わりにArrayListを使用し、返す直前にArrayListを必要な配列型に変換するコードをいくつか示します。

ここでスーパーバイザークラスはISupervisorインターフェイスを実装しますが、Javaではobject [](ArrayListのプレーンtoArray()メソッドが返す)からISupervisor []にキャストできないことに注意してください(できると思います) C#で)、すべてのリストアイテムを反復処理し、結果の配列を設定する必要があります。

/**
 * Get Supervisors for given program id
 * @param connection
 * @param programId
 * @return ISupervisor[]
 * @throws SQLException
 */
public static ISupervisor[] getSupervisors(Connection connection, String programId)
  throws SQLException
{
  ArrayList supervisors = new ArrayList();

  PreparedStatement statement = connection.prepareStatement(SQL.GET_SUPERVISORS);
  try {
    statement.setString(SQL.GET_SUPERVISORS_PARAM_PROGRAMID, programId);
    ResultSet resultSet = statement.executeQuery();  

    if (resultSet != null) {
      while (resultSet.next()) {
        Supervisor s = new Supervisor();
        s.setId(resultSet.getInt(SQL.GET_SUPERVISORS_RESULT_ID));
        s.setFirstName(resultSet.getString(SQL.GET_SUPERVISORS_RESULT_FIRSTNAME));
        s.setLastName(resultSet.getString(SQL.GET_SUPERVISORS_RESULT_LASTNAME));
        s.setAssignmentCount(resultSet.getInt(SQL.GET_SUPERVISORS_RESULT_ASSIGNMENT_COUNT));
        s.setAssignment2Count(resultSet.getInt(SQL.GET_SUPERVISORS_RESULT_ASSIGNMENT2_COUNT));
        supervisors.add(s);
      }
      resultSet.close();
    }
  } finally {
    statement.close();
  }

  int count = supervisors.size();
  ISupervisor[] result = new ISupervisor[count];
  for (int i=0; i<count; i++)
    result[i] = (ISupervisor)supervisors.get(i);
  return result;
}
0
George Birbilis

次の2つのオプションが役に立ちました。

1)ResultSetの行数を返す関数。

private int resultSetCount(ResultSet resultSet) throws SQLException{
    try{
        int i = 0;
        while (resultSet.next()) {
            i++;
        }
        return i;
    } catch (Exception e){
       System.out.println("Error getting row count");
       e.printStackTrace();
    }
    return 0;
}

2)COUNTオプションを使用して2番目のSQLステートメントを作成します。

0
Nico