JavaでREFカーソルを使用する¶
A REF CURSOR is a cursor variable that contains a pointer to a query
result set returned by an OPEN statement. Unlike a static cursor, a REF
CURSOR is not tied to a particular query. You may open the same REF
CURSOR variable any number of times with the OPEN statement
containing different queries; each time, a new result set is created for
that query and made available via the cursor variable. A REF CURSOR can
also pass a result set from one procedure to another.
AdvancedServerは、 strongly-typed と weakly-typed REF CURSORs の両方の宣言をサポートしています。強く型付けされたカーソルは、予想される結果セットの shape (各列の型)を宣言する必要があります。厳密に型指定されたカーソルは、宣言された列を返すクエリでのみ使用できます。異なる形状の結果セットを返すクエリでカーソルを開くと、サーバーは例外をスローします。一方、弱い型指定のカーソルは、任意の形状の結果セットで機能します。
強く型付けされた REF CURSOR を宣言するには:
TYPE <cursor_type_name> IS REF CURSOR RETURN <return_type>;
弱い型付けの REF_CURSOR を宣言するには:
name SYS_REFCURSOR;
.. raw:: latex
\newpage
REFCURSORを使用してResultSetを取得する¶
The stored procedure shown in Listing 1.11-a (getEmpNames) builds two
REF CURSORs on the server; the first REF CURSOR contains a list of
commissioned employees in the emp table, while the second REF CURSOR
contains a list of salaried employees in the emp table:
リスト1.11-a
CREATE OR REPLACE PROCEDURE getEmpNames
(
commissioned IN OUT SYS_REFCURSOR,
salaried IN OUT SYS_REFCURSOR
)
IS
BEGIN
OPEN commissioned FOR SELECT ename FROM emp WHERE comm is NOT NULL;
OPEN salaried FOR SELECT ename FROM emp WHERE comm is NULL;
END;
RefCursorSample() メソッド(リスト1.11-bを参照)は getEmpName() ストアドプロシージャを呼び出し、2つの REF CURSOR 変数のそれぞれに返された名前を表示します。
リスト1.11-b
public void RefCursorSample(Connection con)
{
try
{
con.setAutoCommit(false);
String commandText = "{call getEmpNames(?,?)}";
CallableStatement stmt = con.prepareCall(commandText);
stmt.setNull(1, Types.REF);
stmt.registerOutParameter(1, Types.REF);
stmt.setNull(2, Types.REF);
stmt.registerOutParameter(2, Types.REF);
stmt.execute();
ResultSet commissioned = (ResultSet)stmt.getObject(1);
System.out.println("Commissioned employees:");
while(commissioned.next())
{
System.out.println(commissioned.getString(1));
}
ResultSet salaried = (ResultSet)stmt.getObject(2);
System.out.println("Salaried employees:");
while(salaried.next())
{
System.out.println(salaried.getString(1));
}
}
catch(Exception err)
{
System.out.println("An error has occurred.");
System.out.println("See full details below.");
err.printStackTrace();
}
}
CallableStatement は各 REF CURSOR ( commissioned と salaried )を準備します。各カーソルは、ストアドプロシージャ getEmpNames() の IN OUT パラメーターとして返されます。
String commandText = "{call getEmpNames(?,?)}";
CallableStatement stmt = con.prepareCall(commandText);
registerOutParameter() への呼び出しは、最初のREFCURSOR(委託)のパラメータータイプ(Types.REF)を登録します。
stmt.setNull(1, Types.REF);
stmt.registerOutParameter(1, Types.REF);
registerOutParameter() への別の呼び出しは、2番目の REF CURSOR (salaried) の2番目のパラメーター型( Types.REF )を登録します:
stmt.setNull(2, Types.REF);
stmt.registerOutParameter(2, Types.REF);
stmt.execute() への呼び出しはステートメントを実行します:
stmt.execute();
getObject() メソッドは、最初のパラメーターから値を取得し、結果を ResultSet にキャストします。次に、 RefCursorSample はカーソルを反復処理し、各委託従業員の名前を出力します。
ResultSet commissioned = (ResultSet)stmt.getObject(1);
while(commissioned.next())
{
System.out.println(commissioned.getString(1));
}
同じゲッターメソッドは、2番目のパラメーターから ResultSet を取得し、そのカーソルを介して RefCursorExample を繰り返し、給与を受け取る各従業員の名前を出力します。
ResultSet salaried = (ResultSet)stmt.getObject(2);
while(salaried.next())
{
System.out.println(salaried.getString(1));
}