【问题标题】:Oracle's RETURNING INTO usage in Java (JDBC, Prepared Statement)Oracle 在 Java 中的 RETURNING INTO 用法(JDBC,Prepared Statement)
【发布时间】:2013-06-23 14:24:13
【问题描述】:

我正在使用 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. 如果我将 SQL 语句包装成“BEGIN..END;" - 然后方法 #2 工作得很好。
    • 为什么方法 #1 在没有“BEGIN..END”的情况下可以工作,而方法 #2 需要“BEGIN..END”才能工作?
    • 什么样的“魔法”“BEGIN..END”对语句做了什么让“不是所有的参数都注册”的问题突然解决了?

  2. 是否有第三种更好的方法来执行上述操作?

谢谢你, AG。

【问题讨论】:

  • 方法 1 正在返回结果集,因此 ps.getRetrunResultSet() 可以正常工作。 begin/end 创建了一个匿名 pl/sql 块,它没有返回任何结果集,这就是你需要 execute() 调用的原因。
  • 我在这两种方法中都有 execute() 调用,问题是为什么 begin/end 会导致第二种方法起作用,以及什么是“终极最佳”方法来做我想做的事。谢谢。

标签: java oracle jdbc plsql prepared-statement


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    要获取自动生成的键,我们在 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)); 
        }
    }
    

    【讨论】:

    • 这也是一个很好的解决方案,但是对于 ojdbc8.jar 12.2.0.1,您可能必须应用补丁 26051289(错误 26051289 - 使用 PREPARESTAMENT(STRING, STRING[]) 时的参数无效)。
    猜你喜欢
    • 1970-01-01
    • 2012-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-02
    相关资源
    最近更新 更多