匿名のPL/SQLを実行し、結果セットオブジェクトを取得する必要があります。 PL/SQLブロック内でカーソルを使用して実行できるコードを取得しました。
ただし、PL/SQLブロック自体はデータベースからテキストとして取得されます。そのため、そのPL/SQLブロックを編集することはできません。そして、列名が常に同じになる2つの値のみを返します。 2つの列の組み合わせ値のリストを返します。
ここでは、サンプルのPL/SQLを示します。
BEGIN
RETURN 'select distinct fundname d, fundname r from <table> where condition order by 1';
EXCEPTION
WHEN OTHERS THEN
RETURN 'SELECT ''Not Available'' d, ''Not Available'' r FROM dual';
END;
どんな返信もとても役に立ちます。
これは、「無名PL/SQLを実行して結果セットオブジェクトを取得する」方法の自己完結型の例です。
import Java.sql.CallableStatement;
import Java.sql.Connection;
import Java.sql.DriverManager;
import Java.sql.ResultSet;
import Java.sql.Types;
import Oracle.jdbc.OracleTypes;
public class CallPLSQLBlockWithOneInputStringAndOneOutputStringParameterAndOneOutputCursorParameter {
public static void main(String[] args) throws Exception {
DriverManager.registerDriver(new Oracle.jdbc.OracleDriver());
// Warning: this is a simple example program : In a long running application,
// error handlers MUST clean up connections statements and result sets.
final Connection c = DriverManager.getConnection("jdbc:Oracle:thin:@localhost:1521:XE", "system", "manager");
String plsql = "" +
" declare " +
" p_id varchar2(20) := null; " +
" l_rc sys_refcursor;" +
" begin " +
" p_id := ?; " +
" ? := 'input parameter was = ' || p_id;" +
" open l_rc for " +
" select 1 id, 'hello' name from dual " +
" union " +
" select 2, 'peter' from dual; " +
" ? := l_rc;" +
" end;";
CallableStatement cs = c.prepareCall(plsql);
cs.setString(1, "12345");
cs.registerOutParameter(2, Types.VARCHAR);
cs.registerOutParameter(3, OracleTypes.CURSOR);
cs.execute();
System.out.println("Result = " + cs.getObject(2));
ResultSet cursorResultSet = (ResultSet) cs.getObject(3);
while (cursorResultSet.next ())
{
System.out.println (cursorResultSet.getInt(1) + " " + cursorResultSet.getString(2));
}
cs.close();
c.close();
}
}
上記の例は、「select 1 id、 'hello' name from dual union select 2、 'peter' from dual;」というクエリです。任意のクエリで置き換えることができます。
次のようなものを試してください(疑似コード):
[create or replace] function get_dataset (p_query in varchar2) return sys_refcursor
as
l_returnvalue sys_refcursor;
begin
open l_returnvalue for p_query;
return l_returnvalue;
end get_dataset;
返されるREF CURSORは、通常のデータセットのように処理できます。
そしてSQLインジェクションに注意このようなアプローチを使用すると...
まず、投稿したコードが無効です。無名PL/SQLブロックは式を返すことができません。そして、そのようなクエリの結果を返すPL/SQLブロックはありません。 REF CURSORを宣言し、さまざまなSQLステートメントを使用してそのカーソルを開くなどの操作を行う必要があります。
無名のPL/SQLブロックは呼び出し元に何も返すことができないため、ここで説明しているアーキテクチャには問題があります。少なくとも、JDBCコードが登録できるバインド変数が存在するように匿名ブロックを変更する必要があります。 ( MenonのエキスパートOracle JDBCプログラミング の例から適応)のようなもの(私はいくつかの小さな構文エラーを導入した可能性があることに注意してください)
CallableStatement stmt := null;
ResultSet rset := null;
String query := 'DECLARE
FUNCTION get_result
RETURN SYS_REFCURSOR
AS
l_rc SYS_REFCURSOR;
BEGIN
OPEN l_rc
FOR SELECT DISTINCT fundname d, fundname r
FROM some_table
WHERE some_condition
ORDER BY 1;
RETURN l_rc;
EXCEPTION
WHEN others THEN
OPEN l_rc
FOR SELECT 'Not Available' d, 'Not Available' r
FROM dual;
RETURN l_rc;
END get_result;
BEGIN
? := get_result;
END;';
try {
cstmt := conn.prepareCall( query );
cstmt.registerOutParameter( 1, OracleTypes.CURSOR );
cstmt.execute();
rset := (ResultSet) cstmt.getObject( 1 );
}
finally {
<<close cstmt & rset>>
}