insert文などでシーケンスを使用して採番を行った値を取得する場合、
JDBCの自動採番キー機能と、Oracleの拡張SQL文を使用する2パターンの方法がある。
Oracle拡張機能を使用した場合、1レコード更新なら良いが複数レコード更新になると、
クライアント側コードもOracleが拡張したJDBCの機能を使う必要があり、ちと面倒になる。
JDBCの自動採番キー機能
// Statement取得時に、自動採番キーの項目を第二引数で指定する。
// この例では、ID列がシーケンスでの採番対象なので『ID』と指定している。
PreparedStatement statement = con.prepareStatement(
"insert into test (ID, NAME) values (TEST_SEQ.nextval, ?)",
new String[]{"ID"});
try {
statement.setString(1, "hogehoge");
statement.execute();
// SQLを実行後、statementオブジェクトからgetGeneratedKeysを呼び出して、
// 採番キーの結果を取得する。(1行だけなのにResultSetってのが面倒・・・)
ResultSet keys = statement.getGeneratedKeys();
try {
// ResultSetと同じ感じに値を取得する。
// ただし、カラム名指定でのアクセスは出来ないので、
// インデックス指定でアクセスする必要がある。
keys.next();
int id = keys.getInt(1);
System.out.println("id = " + id);
} finally {
keys.close();
}
} finally {
statement.close();
}
con.commit();
}
Oracleの拡張SQL機能
// Oracleで拡張された、returning intoを使用して、
// IDカラムの値をバインド変数(OUTパラメータに代入する。)
// なお、SQL文はbegin endで囲い、無名pl/sqlにする必要がある。
CallableStatement statement = con.prepareCall(
"begin insert into test (ID, NAME) "
+ " values (TEST_SEQ.nextval, ?) returning id into ?; end;");
try {
statement.setString(1, "hoge");
// OUTパラメータのタイプを指定する。
statement.registerOutParameter(2, Types.INTEGER);
statement.execute();
// SQL実行後に、OUTパラメータの値を取得する。
int id = statement.getInt(2);
System.out.println("id = " + id);
con.commit();
} finally {
statement.close();
}
Oracleの拡張SQL機能で複数行更新の場合
// returning intoを使用してID列をOUTパラメータに代入する。
// SQL文は、通常のSQL文形式で、statementはOracleJDBCのstatementにキャストする。
OracleCallableStatement statement = (OracleCallableStatement)
con.prepareCall("update test set id = test_seq.nextval returning id into ?");
try {
// registerReturnParameterを呼び出して、データ型を設定する。
// なお、この時に設定するデータ型はOracleTypesがもつ定数を使用する。
statement.registerReturnParameter(1, OracleTypes.INTEGER);
int count = statement.executeUpdate();
System.out.println("count = " + count);
// getReturnResultSetを呼び出して、OUTパラメータの結果セット(ResultSet)を取得する。
ResultSet set = statement.getReturnResultSet();
try {
while (set.next()) {
System.out.println("set.getInt(1) = " + set.getInt(1));
}
} finally {
set.close();
}
} finally {
statement.close();
}