アプリ版:「スタンプのみでお礼する」機能のリリースについて

dbからデータをとりだす際、sqlのfetch結果をjavaでとりだすのは可能なのでしょうか?

(チェックボックス 空欄) sql (チェックボックス 空欄)
begin;
declare cursor_name cursor
for
select * from user_ad;

fetch forward 3 from cursor_name; //この結果をjavaでとりだしたい

注:この後、PostgreslqMyAdminで表そうとしたら、commitしたら表せない!!

ふつうに、select文でとりだすなら分かるのですが。。。

con = Connectionのこと

処理ソースは、、、

必要最小限な部分だけ、記述しています。

PrepareStatement stmt = null;

try {
String sql = "select user_id from user_ad";
this.stmt = con.prepareStatement(sql);
//ループでデータとりだし
ResultSet rs = stmt.executeQuery();
while(rs.next()) {
String userId = rs.getString("user_id");
}
}catch(Exception e) {
System.out.println(e.getMessage());
System.out.println(e.getStackTrace());

}

fetchでとりだそうとすると、カーソルが関係していて、処理自体、変わってくるのでしょうか?

よろしくお願いします。

A 回答 (3件)

「fetch forward 3 from cursor_name」というSQLはPostgreSQLの拡張なので、


PostgreSQLのJDBCドライバであれば
Statement#setFetchSize()で指定行数を取得することは実行可能のようです。
(根拠 → 
http://www.postgresql.jp/document/pg743doc/html/ …
ただし未検証の上、PostgreSQL7.4.3のドキュメントなので断言できませんが。

前のレスで、「ResultSetオブジェクトに・・・結果をセットしています」といいましたが
実際には
1.データベースよりデータを取得してメモリ上にデータキャッシュ
2.仮想テーブルのキャッシュデータへポインタをあてる
という状態となります。
(下記が参考になると思います
http://www.atmarkit.co.jp/fjava/rensai2/jspservl …
Statement#setFetchSize()でできることは
この仮想テーブルへのデータキャッシュについて、
デフォルトは全件とってきて乗せるところを
指定行数ずつ乗せるよう変えられるのだと思います。
またキャッシュ範囲がrs.next() で超えた場合、
次のデータ取り出しを自動に行います。
(参考:
http://inoccu.net/blog/tag/seaser2/)
そのためrs.next()でループすると3件どころか全部出てくるのだと考えられます。
(DB2で検証したところそうなりました)

ただしドキュメントを読む限り、
PostgreSQLのJDBCドライバでは違う挙動、
すなわちStatement#setFetchSize()で指定した行数だけ取得するみたいです。
ただしそれはStatement#setMaxRows()を指定したときと同じ動作だと思いますが。


>また、どうしても分りにくいのですが、
>「ResultSet オブジェクトでより多くの行が必要なときにデータベースから取り出す必要がある行数」
>= つまり、これはdbからとりだすデータがselect結果より多い時と少ない時では、多い時に有効なのでしょうか?

setFetchSize()を使う目的は、パフォーマンスチューニングです。
たとえばデータベースのレコードが100万件もあるような膨大なデータを扱うとき、
この100万件を一気にメモリへキャッシュすることは
大きなパフォーマンス劣化とメモリ資源消費の懸念があります。
メモリの積載が少ないPCでは、エラーが発生してしまうでしょう。
これらを補うためsetFetchSize()でフェッチ件数を調整し、
パフォーマンスの向上を図ることが可能になります。
    • good
    • 0
この回答へのお礼

ありがとうございます。


setFetchSize()を使う目的は、パフォーマンスチューニングです。
たとえばデータベースのレコードが100万件もあるような膨大なデータを扱うとき、
この100万件を一気にメモリへキャッシュすることは
大きなパフォーマンス劣化とメモリ資源消費の懸念があります。
メモリの積載が少ないPCでは、エラーが発生してしまうでしょう。
これらを補うためsetFetchSize()でフェッチ件数を調整し、
パフォーマンスの向上を図ることが可能になります。

これについては、fetchSize()で件数を决めると、確かに、パフォーマンス上いいようなきがします。。。

その後色いろ試したところ、fetchSize()を指定し、それをwhileでループさせれば、fetchSize分とりだせるようになったのですが、、、

時間があきすぎたので、再度while文で質問するので、よければ回答お願いします。

ありがとうございました、とても参考になりました。。。

お礼日時:2010/06/16 06:38

No1で示したAPIは、


ResultSetオブジェクトには3件ずつ
フェッチでDBアクセスして結果をセットしています。
しかしnext()で呼び出す時点では全件セットし終わった後になります。
質問者さんは3件セット毎に
結果セットの編集もしくは参照がしたいのですよね。
そういう場合には適してないようです。
どうもすみませんでした。

データベース製品によって、ベンダーの提供しているSQLドライバで
フェッチカーソルの扱いも違いがあるようです。
質問者さんの使用しているデータベースの製品名とバージョンはなんでしょう?

この回答への補足

ありがとうございます。

使用DBは、Postgresqlでバージョンは、PostgreSQL Database Server 8.1です。

>
ResultSetオブジェクトには3件ずつ
フェッチでDBアクセスして結果をセットしています。

というと、3件づつのかたまりで順にResultSetに渡されていると考えていいのでしょうか?
fetchSize()を使用しなければ、全てが順にResultSetに渡される。

javaの、StatementのsetFetchSize(),getFetchSize()を見てみたのですが、

この Statement で作成された ResultSet オブジェクトでより多くの行が必要なときにデータベースから取り出す必要がある行数についてのヒントを JDBC ドライバに提供します。指定された値が 0 の場合、ヒントは無視されます。デフォルト値はゼロです。

これを見ると、dbからとりだすデータの行を指定できると言ってはいるのでしょうか?
fetchSizeを指定しなかったら、select結果全てがとりだされる、というわけではないのでしょうか?

また、どうしても分りにくいのですが、
「ResultSet オブジェクトでより多くの行が必要なときにデータベースから取り出す必要がある行数」
= つまり、これはdbからとりだすデータがselect結果より多い時と少ない時では、多い時に有効なのでしょうか?


よろしくお願いします。

補足日時:2010/06/11 06:07
    • good
    • 0

フェッチで結果セットを3行ずつResultSetにのせることは


次のコーディングで可能です

Statement stmt = con.createStatement();
stmt.setFetchSize(3);
ResultSet rs = stmt.executeQuery("実行SQL");

参考URLで解説がありましたので一読してみてください。

参考URL:http://java.sun.com/j2se/1.5.0/ja/docs/ja/guide/ …

この回答への補足

ありがとうございます。
参考URL共に、確認してみました。

その場合どうしても分らないのですが、

rsの結果を3行とりだすには、
while(rs.next()){}を使用すると、fetchSizeに関係なく、全部とりだされてしまうのですが、
この場合、3行だけとりだすにはどうすべきなのでしょうか?

stmt.getFetchSize();では、3行とれているので、このメソッドを使用して処理するのかと思ったのですが。

よろしくお願いします。

補足日時:2010/06/10 09:25
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!