我正在使用JDBC执行Oracle语句,它看起来像这样:
"INSERT INTO MYTABLE(MYDATA) VALUES(?) RETURNING MY_CALCULATED_DATA INTO ?"
// MYTABLE's def makes MY_CALCULATED_DATA be auto-generated by DB on insert
我找到了几种在Java中调用上述语句的方法,主要是:
使用OraclePreparedState:
ps = (OraclePreparedStatement)conn.prepareStatement(sql); ps.setString(1, "myvalue"); ps.registerReturnParameter(2, Types.VARCHAR); ps.execute(); rs = ps.getReturnResultSet(); rs.next(); System.out.print(rs.getString(1));
使用可调用语句:
cs = conn.prepareCall(sql); cs.setString(1, "myvalue"); cs.registerOutParameter(2, Types.VARCHAR); cs.execute(); System.out.print(cs.getString(1));
问题:
- 方法#2抛出"SQLException:并非所有返回参数都已注册",但,如果我将SQL语句包装成"BEGIN..END;",则方法#2工作正常。
- 为什么方法#1在没有"BEGIN..END"的情况下工作,而方法#2需要"BEGIN..END"才能工作
- "BEGIN..END"对语句做了什么样的"魔术",使"并非所有参数都已注册"的问题突然自行解决?
- 有没有第三种更好的方法可以做到这一点
谢谢,AG.
因为与正常输出参数相比,返回子句中指定的参数的处理方式不同(getReturnResultSet与getResultSet与callablestatement中的返回参数)
它们需要使用OraclePreparedStatement进行处理。在第二种情况下,当您将insert语句包装在begin..中时。。最后,插入由数据库本身处理,al-jdbc看到的是一个匿名的plsql块
http://docs.oracle.com/cd/E11882_01/java.112/e16548/oraint.htm#BABJJDDA
要获得自动生成的密钥,我们在preparetatement中有getGeneratedKeys方法,该方法返回包含键值的结果集,我们只需要将密钥列名传递给preparetatement
pstm = con.prepareStatement("insert query",new String[]{primarykeycolumnname});
int i = pstm.executeUpdate();
if (i > 0)
{
ResultSet rs = pstm.getGeneratedKeys();
while(rs.next())
{
System.out.println(rs.getString(1));
}
}