これは不可能です。無名PL/SQLブロックから結果セットを返すことはできません(したがって、JDBCから結果セットを取得する方法はありません)。
JDBC から直接選択を実行する必要があります。
唯一の、本当に醜い回避策は、使用dbms_output.put_line()
して後でそれを読むことです。しかし、これは非常に厄介なハックであり、SELECT クエリの結果を JDBC で直接処理する方がはるかに優れています。
編集 1
dbms_output を使用した小さな例を次に示します。
Connection con = ....;
// turn on support for dbms_output
CallableStatement cstmt = con.prepareCall("{call dbms_output.enable(32000) }");
cstmt.execute();
// run your PL/SQL block
Statement stmt = con.createStatement();
String sql =
"declare \n" +
" a number; \n" +
" cursor c1 is select id from foo; \n" +
"begin \n" +
" open c1; \n" +
" loop \n" +
" fetch c1 into a; \n" +
" exit when c1%notfound; \n" +
" dbms_output.put_line('ID: '||to_char(a)); \n" +
" end loop; \n" +
"end;";
stmt.execute(sql);
// retrieve the messages written with dbms_output
cstmt = con.prepareCall("{call dbms_output.get_line(?,?)}");
cstmt.registerOutParameter(1,java.sql.Types.VARCHAR);
cstmt.registerOutParameter(2,java.sql.Types.NUMERIC);
int status = 0;
while (status == 0)
{
cstmt.execute();
String line = cstmt.getString(1);
status = cstmt.getInt(2);
if (line != null && status == 0)
{
System.out.println(line);
}
}
編集 2 (これはコメントには長すぎます)
データを取得するためにループをネストすることは、ほとんどの場合、悪い考えです。あなたがこのようなことをしているのを見つけたら:
begin
for data_1 in (select id from foo_1) loop
dbms_output.put_line(to_char(data_1.id));
for data_2 in (select f2.col1, f2.col2 from foo_2 f2 where f2.id = data_1.id) loop
... do something else
end loop;
end loop;
end;
/
次のようにすると、はるかに効率的になります。
begin
for data_1 in (select f2.col1, f2.col2 from foo_2 f2
where f2.id in (select f1.id from foo_1 f1)) loop
... do something
end loop;
end;
/
これは、次のようなものを使用して、JDBC で過剰なメモリなしで処理できます。
String sql = "select f2.col1, f2.col2 from foo_2 f2 where f2.id in (select f1.id from foo_1 f1)";
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql);
while (rs.next())
{
String col1_value = rs.getString(1);
int col2_value = rs.getInt(2);
... do something
}
上記のコードは、数十億行を処理する場合でも、メモリ内に 1 行しか保持しません。正確に言うと、JDBC ドライバーは実際には複数の行をプリフェッチします。デフォルトは 10 で、変更できます。それでも、過度のメモリ使用量はありません。