【问题标题】:JDBC: ORCLE stored procedures with return-value in batch-processingJDBC:在批处理中具有返回值的 ORACLE 存储过程
【发布时间】:2019-02-19 11:34:30
【问题描述】:

我有一个 JDBC 连接到一个 Oracle RDBMS。

我需要调用一个返回数字的存储过程(我们将其命名为 foo)。

如果我为自己执行每条语句,它就可以正常工作。

for (int i = 0; i < 10;i ++)
{
  CallableStatement cst = con.prepareCall ("{? = foo (" + i + ")}");
  cst.registerOutParameter (1, Types.INTEGER);
  cst.execute ();
}

现在我喜欢使用批处理来提高性能。这就是我的方法。

Statement st = con.createStatement ();
for (int i = 0; i < 10;i ++)
{
  st.addBatch ("{? = foo (" + i + ")}");
}
st.executeBatch ();

这行不通。

错误告诉我并非每个变量都已分配。认为这是因为在上面的工作示例中没有注册返回值。

如果我将语句设置为

{foo (" + i + ")}

要删除返回,然后我会收到未定义过程的错误。

如何在批处理中处理这种带有返回值的存储过程?

【问题讨论】:

    标签: oracle jdbc plsql


    【解决方案1】:

    一个 JDBC 批处理需要一个相同的预处理语句和一堆绑定变量。

    你违反了这一点,动态声明 "{? = foo (" + i + ")}" 为每个 i 生成。

    您必须使用带有两个绑定变量的单个语句"{? = foo (?)}"

    不幸的是,这导致了异常

    捕获:java.sql.SQLException:不允许操作:无法批处理带有 out 或 inout 参数的存储过程

    因为不可能从批处理语句返回结果函数调用的集合。

    幸运的是,有一个非常简单的替代解决方案。您可以使用 prepareStatement 来模拟批处理 (即您将往返限制到数据库服务器)

     def stmt = con.prepareStatement("select foo(rownum) foo from dual connect by level <= 10")
    

    fetch site 设置为与 batch size 相同,您将获得该行为。

    【讨论】:

    • 谢谢!我喜欢注释初始化所有变量,甚至是返回值(第一个变量)所需的内容。但不允许注册为输出变量。
    • @chris01 你是对的。我添加了一些替代方案来解决这个问题。
    猜你喜欢
    • 2019-06-03
    • 1970-01-01
    • 2013-07-24
    • 1970-01-01
    • 2017-06-30
    • 2014-11-13
    • 2014-05-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多