第6章 ストアド関数の呼び出し

目次

ストアド関数からResultSetを入手
SETOF型を返す関数から
refcursorを返す関数から

PostgreSQL™のJDBCドライバは、PostgreSQL™のストアド関数の呼び出しを完全にサポートします。

注意

CallableStatementのサポートは、バックエンドのストアドプロシージャサポートと同等です。 PostgreSQL™は出力パラメータを持つ関数をサポートしていません。 これは、関数の戻り値以外に対してregisterOutParameterを使用することができないことを意味します。

例 6.1. 組み込みストアド関数の呼び出し

この例は、PostgreSQL™の組み込み関数upperの呼び出し方法を示します。 この関数は単に与えられた文字列引数を大文字に変換します。

CallableStatement upperProc = conn.prepareCall("{ ? = call upper( ? ) }");
upperProc.registerOutParameter(1, Types.VARCHAR);
upperProc.setString(2, "lowercase to uppercase");
upperProc.execute();
String upperCased = upperProc.getString(1);
upperProc.close();

ストアド関数からResultSetを入手

PostgreSQL™のストアド関数は2つの方法で結果を返すことができます。 関数はrefcursor値として、または、何らかのデータ型のSETOFを返すことができます。 使用される戻り値の種類に応じて、関数の呼び出し方法が決まります。

SETOF型を返す関数から

セットとしてデータを返す関数をCallableStatementインタフェース経由で呼び出してはいけません。 その代わりに、通常のStatementPreparedStatementインタフェースを使用してください。

例 6.2. 関数からSETOF型の値を取り出す

Statement stmt = conn.createStatement();
stmt.execute("CREATE OR REPLACE FUNCTION setoffunc() RETURNS SETOF int AS "
		+ "' SELECT 1 UNION SELECT 2;' LANGUAGE sql");
ResultSet rs = stmt.executeQuery("SELECT * FROM setoffunc()");
while (rs.next()) {

    // 何らかの処理
}
rs.close();
stmt.close();

refcursorを返す関数から

refcursorを返す関数を呼び出す場合、getObjectの戻り値の型をResultSetにキャストしなければなりません。

注意

refcursorから作成されるResultSetのサポートに関して、現在注意しなければならない制限が1つあります。 カーソルとしてResultSetに返される場合であっても、すべてのデータを受け取り、クライアントにキャッシュされるという点です。 カーソルに基づいた結果の入手項で説明した、Statementの取り出しサイズは無視されます。 この制限は、サーバ側ではなくJDBCドライバの問題で、技術的には取り除くことができます。時間が取れないだけです。

例 6.3. 関数からrefcursor値を得る


// 関数呼び出しの設定
Statement stmt = conn.createStatement();
stmt.execute("CREATE OR REPLACE FUNCTION refcursorfunc() RETURNS refcursor AS '"
		+ " DECLARE "
		+ "    mycurs refcursor; "
		+ " BEGIN "
		+ "    OPEN mycurs FOR SELECT 1 UNION SELECT 2; "
		+ "    RETURN mycurs; "
		+ " END;' language plpgsql");
stmt.close();


// カーソルを動作させるためにトランザクション内部にしなければなりません。
conn.setAutoCommit(false);


// プロシージャを呼び出し
CallableStatement proc = conn.prepareCall("{ ? = call refcursorfunc() }");
proc.registerOutParameter(1, Types.Other);
proc.execute();
ResultSet results = (ResultSet) proc.getObject(1);
while (results.next()) {

    // 結果に対して何らかの処理を行う
}
results.close();
proc.close();

refcursor戻り値をカーソル名として直接扱うこともできます。 このためには、ResultSetgetStringを使用してください。 背後のカーソル名を使って、自由に、FETCHMOVEなどのカーソルコマンドを直接使用することができます。

例 6.4. refcursorをカーソル名として扱う

conn.setAutoCommit(false);
CallableStatement proc = conn.prepareCall("{ ? = call refcursorfunc() }");
proc.registerOutParameter(1, Types.Other);
proc.execute();
String cursorName = proc.getString(1);
proc.close();