为啥我在从 Java 批量执行 PostgreSQL 存储过程时收到错误消息,提示“未预期结果”?
Posted
技术标签:
【中文标题】为啥我在从 Java 批量执行 PostgreSQL 存储过程时收到错误消息,提示“未预期结果”?【英文标题】:Why I'm getting an error informing that "a result was not expected" when executing stored procedures on PostgreSQL from Java in a batch?为什么我在从 Java 批量执行 PostgreSQL 存储过程时收到错误消息,提示“未预期结果”? 【发布时间】:2011-09-02 03:29:26 【问题描述】:我在数据库中有这个程序:
CREATE OR REPLACE FUNCTION replacePageRelevance(id INT, value REAL) RETURNS VOID AS $$
BEGIN
INSERT INTO pageRelevance VALUES (id,value);
EXCEPTION WHEN unique_violation THEN
UPDATE pageRelevance SET relevance = value WHERE pageId = id;
END
$$
LANGUAGE plpgsql;
以及调用此函数的这段代码:
private final String PAGE_RELEVANCE_SQL = "SELECT replacePageRelevance(?,?::REAL)";
try (CallableStatement cstm = conn.prepareCall(PAGE_RELEVANCE_SQL))
for (Map.Entry<Integer, Double> entry : weightMap.entrySet())
cstm.setInt(1, entry.getKey());
cstm.setDouble(2, entry.getValue());
cstm.addBatch();
cstm.executeBatch();
catch (SQLException e)
LOGGER.error("Error discovering pages relevance: " + e.getNextException());
当我执行批处理时,值被插入或替换到表中,但在那之后,我收到一个异常通知 A result was returned when none was expected.
我不知道出了什么问题,是我调用程序的方式还是程序本身。可能是什么问题以及如何解决?
使用SELECT
调用过程是正确/唯一的方法吗?
【问题讨论】:
【参考方案1】:据我所知,您在应该使用 call
时使用的是 SELECT
。
来自PostgreSQL documentation on the JDBC interface的一个例子:
// Turn transactions off.
con.setAutoCommit(false);
// Procedure call.
CallableStatement upperProc = con.prepareCall(" ? = call upper( ? ) ");
upperProc.registerOutParameter(1, Types.VARCHAR);
upperProc.setString(2, "lowercase to uppercase");
upperProc.execute();
String upperCased = upperProc.getString(1);
upperProc.close();
请注意,在您的情况下,结果的 ? = call
语法是不必要的 - 您只想使用 call replacePageRelevance(?,?::REAL)
此语法与实际 PostgreSQL 不同的原因是因为这是 JDBC specification 的一部分。
【讨论】:
@Renato - 你试过了吗? postgresql.org/docs/7.4/static/jdbc-callproc.html(找不到 9.0 的文档) 我只尝试用 CALL 代替 SELECT。我正在尝试使用此示例,但我的函数返回 VOID。 感谢您的帮助,与 call 合作。我只想强调call
必须小写。
@Renato - 啊,没有意识到,我的错误。回答已编辑并 +1,因为我也学到了一些东西。以上是关于为啥我在从 Java 批量执行 PostgreSQL 存储过程时收到错误消息,提示“未预期结果”?的主要内容,如果未能解决你的问题,请参考以下文章
为啥在从 C# 创建的进程中运行 bash 命令时我的 $PATH 不同?
为啥我在从 MS Access 数据库中提取的十进制值中添加了零?