21

我正在使用 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中调用上述语句的方法,主要是:

  • 使用 OraclePreparedStatement:

    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));
    
  • 使用 CallableStatement:

    cs = conn.prepareCall(sql);
    cs.setString(1, "myvalue");
    cs.registerOutParameter(2, Types.VARCHAR);
    cs.execute();
    System.out.print(cs.getString(1));
    

问题:

  1. 方法 #2 抛出"SQLException: Not all return parameters registered"但是,如果我将 SQL 语句包装成 " BEGIN..END; " - 那么方法 #2 工作得很好。
    • 为什么方法 #1 可以在没有“ BEGIN..END ”的情况下工作,但方法 #2 需要“ BEGIN..END ”才能工作?
    • 什么样的“魔法”“ BEGIN..END ”对语句做了什么让“不是所有参数都注册”的问题突然解决了?

  2. 有没有第三种更好的方法来做上述事情?

谢谢你,AG。

4

2 回答 2

6

因为与正常输出参数相比,返回子句中指定的参数以不同的方式处理(getReturnResultSet vs getResultSet vs 在可调用语句中返回参数)。
它们需要使用 OraclePreparedStatement 进行处理。在第二种情况下,当您将插入语句包装在 begin..end 中时,插入由数据库本身处理,并且 jdbc 看到的是一个匿名 plsql 块。
http://docs.oracle.com/cd/E11882_01/java.112/e16548/oraint.htm#BABJJDDA

于 2014-02-07T12:10:22.060 回答
4

要获取自动生成的键,我们在 preparestatement 中有方法 getGeneratedKeys 方法,它返回包含键值的结果集,我们需要将键列名称传递给 preparestatement

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)); 
    }
}
于 2013-12-05T12:57:53.723 回答