JDBCのCallableStatementは、
プロシージャ(DBMS内に定義されているサブルーチン・関数)を呼び出すステートメント。
PreparedStatementを継承している。
import java.sql.CallableStatement;
OracleのUPDATE・INSERT・DELETE文には、処理対象レコードの値を返すRETURNING句というものがある。
CallableStatementを使って、その値を取得できる。
String sql = "begin update EMP set SAL=SAL+1 where ENAME=? returning EMPNO into ?; end;"; CallableStatement stat = conn.prepareCall(sql); try { stat.setString(1, "SCOTT"); stat.registerOutParameter(2, Types.INTEGER); stat.execute(); System.out.println(stat.getInt(2)); } finally { stat.close(); }
直接returning付きのSQL文を実行すると「プロトコル違反です」というSQLExceptionが発生するので、begin〜endで囲んでPL/SQLブロックにしている。
SQL文の中には、PreparedStatementと同様に「?」でパラメーターを指定することが出来る。
PreparedStatementではパラメーターには値を渡すだけだが、CallableStatementでは実行結果の値を受け取れる。
値を指定する場合は実行前にset系メソッドを呼んで値をセットするが、
結果を受け取る場合は実行前にregisterOutParameter()メソッドを呼んで型を指定しておき、実行後にget系メソッドを呼んで値を取得する。
この際のパラメーター番号は、入出力の種類を問わず、全ての「?」を通しての連番となる。
この方式では、SQLの実行結果が1件の場合だけ値が取得できる。
0件だった場合はnullが返る(getInt()なら0が返る)。
2件以上の場合はエラーとなる。(java.sql.SQLException: ORA-01422: 完全フェッチが要求よりも多くの行を戻しました
)