可调用语句 - PostgreSQL - 多个输出参数

Posted

技术标签:

【中文标题】可调用语句 - PostgreSQL - 多个输出参数【英文标题】:Callable Statement - PostgreSQL - Multiple Out Parameters 【发布时间】:2022-01-22 19:06:24 【问题描述】:

我们在 PostgreSQL 数据库中有一个存储过程,它接受多个输入和多个输出参数。当我们执行以下操作时,来自 PG Admin 客户端的过程调用可以正常工作,

调用 proc1(input1, input2, output1, output2)

但是,如果我们尝试通过 JDBC CallableStatement 进行此调用,则会收到以下错误,

org.postgresql.util.PSQLException: This statement does not declare an OUT parameter.  Use  ?= call ...  to declare one.
    at org.postgresql.jdbc.PgCallableStatement.registerOutParameter(PgCallableStatement.java:205)

PostgreSQL 驱动程序是“org.postgresql.Driver”

驱动版本是postgressql-42.2.5.jar

我们如何从 JDBC 调用具有多个输出参数的 PostgreSQL 过程?

请在下面找到代码sn-p,

public static void main(String args[]) throws SQLException 
        Connection conn = null;
        try 
            String url = "jdbc:postgresql://<<hostname>>:<<port>>/<<DB>>";

            Class.forName("org.postgresql.Driver");
            
            Properties props = new Properties();
            props.setProperty("user", "<<user>>");
            props.setProperty("password", "<<pass>>");
            
            conn = DriverManager.getConnection(url, props);
            CallableStatement cs = conn.prepareCall("call schema.proc1(?,?,?,?)");
            
            cs.setString(1, "test");
            cs.setInt(2, 1000);
            cs.registerOutParameter(3, Types.INTEGER);
            cs.registerOutParameter(4, Types.VARCHAR);
            
            cs.execute();
            
         catch (Exception e) 
            log.error(e);
         finally 
            if (conn != null) 
                conn.close();
            
        

以下是程序的示例版本

Procedure proc1 is (input1 IN varchar2(10), 
      input2 IN number, output1 OUT number, 
      output2 OUT varchar2(10)) IS
BEGIN
output2 := input1;
output1 := input2;
END;

【问题讨论】:

请提供minimal reproducible example,其中包含您正在执行的存储过程的基本(简化)示例以及您用来执行的 Java 代码。 你确定程序是在 PostgreSQL 数据库中定义的吗?语法类似于Oracle... 是的,程序是从Oracle最近迁移到PostgreSQL的。 PostgreSQL 的源副本并不方便,因此添加了该过程的 Oracle 版本。从 pgAdmin 客户端运行时,PostgreSQL 过程没有问题并且运行良好。但是,当从 JDBC 调用时,它会引发上述错误。这似乎是对驱动程序的一些限制。 【参考方案1】:

我正在使用 PostgreSQL 14.1 和驱动程序 42.2.20 在 JDBC 中使用 多个 OUT 参数 测试过程调用。

必须小心,因为 ANSI 调用失败

cn.prepareCall("call proc1(?,?,?,?)")

with org.postgresql.util.PSQLException: ERROR: proc1(character varying, integer) is a procedure Hint: To call a procedure, use CALL. 这可能与this 回答有关

类似的 PostgreSQL CALL cn.prepareCall("call proc1(?,?,?,?)") 也失败了

Caught: org.postgresql.util.PSQLException: ERROR: invalid input syntax for type integer: "null"。这表明 nullinteger OUTparamater 存在问题。

我终于通过一点hackinteger 参数定义为INOUT 并传递零来得到它。

程序

create or replace PROCEDURE proc1(input1 IN varchar(10), input2 IN integer, output1 INOUT integer, output2 OUT varchar(10))
LANGUAGE plpgsql
AS $$
BEGIN
output2 := input1;
output1 := input2;
END;
$$;

JDBC

// procedure call with two OUT parameter 
stmt = cn.prepareCall("call proc1(?,?,?,?)") 
stmt.setString(1,'x')
stmt.setInt(2,100)
stmt.setInt(3,0)
stmt.registerOutParameter(3,Types.INTEGER)
stmt.registerOutParameter(4,Types.VARCHAR)
stmt.execute()
println  stmt.getInt(3)
println  stmt.getString(4)

按预期返回

100
x

【讨论】:

仅使用VARCHAR的类似答案 感谢您的回复/回答。这很有帮助。我们让它工作,无需将 OUT 更改为 INOUT,而是将默认的非空值(如 0 或 >)传递给 OUT 参数,然后获取结果集并迭代结果。

以上是关于可调用语句 - PostgreSQL - 多个输出参数的主要内容,如果未能解决你的问题,请参考以下文章

将'select from dual'作为参数传递给java可调用语句

异常:可调用语句未返回任何值

如何将自定义类型作为输入参数放入可调用语句中

执行可调用语句时出现 SQLException

Java中的可调用语句不起作用

使用 JDBC 可调用 stmt 存储 proc 时返回的结果集的顺序是啥?