在 Java 中,调用 PostgreSQL 函数,为啥我收到一个错误,通知该函数不存在?

Posted

技术标签:

【中文标题】在 Java 中,调用 PostgreSQL 函数,为啥我收到一个错误,通知该函数不存在?【英文标题】:In Java, calling a PostgreSQL function, why I'm getting an error informing that the function doesn't exists?在 Java 中,调用 PostgreSQL 函数,为什么我收到一个错误,通知该函数不存在? 【发布时间】:2011-09-01 17:16:51 【问题描述】:

我在数据库中有这个程序:

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;

以及调用此函数的这段代码:

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());
    

这不起作用,我收到一条错误消息,通知 function replacepagerelevance(integer, double precision) doesn't exists.。为什么?

生成的调用是这样的:SELECT replacePageRelevance('882','8.0')。如果我在 pgAdmin 中执行它,它可以工作,但不是来自 Java。

【问题讨论】:

【参考方案1】:

这是因为您的 PL/pgSQL 函数定义为:

replacePageRelevance(id INT, value REAL)

REAL 是单精度浮点数,但在 Java 端,您尝试将其用作双精度,并且没有针对这种情况的隐式转换。

您应该使用 CallableStatement.setFloat 单精度 REAL 数据类型,但它并不清楚,因为阅读 Java API:

将指定参数设置为给定的 Java 浮点值。这 驱动程序在将其发送到 数据库。

由于 FLOAT 在 Postgres 中是 DOUBLE PRECISION同义词,它的运行效果与 CallableStatement.setDouble 产生错误消息的效果相同(这很奇怪)。

当然,您可以将您的函数更改为 replacePageRelevance(id INT, value DOUBLE PRECISION),并且我检查过它适用于您的代码。

尽管如此,如果你想在你的函数中保留REAL),那么使用这样的显式转换:

String PAGE_RELEVANCE_SQL = "call replacePageRelevance(?, ?::real)";

【讨论】:

什么PostgreSQL类型兼容双精度? @Renato:就double precision 感谢您的回答和解释。我现在正在使用转换,因为我不需要太多的精度

以上是关于在 Java 中,调用 PostgreSQL 函数,为啥我收到一个错误,通知该函数不存在?的主要内容,如果未能解决你的问题,请参考以下文章

无法从 java 调用我在 postgresql 中的函数

数据库中的 PostgreSQL 函数

Postgresql 11:存储过程调用错误 - 要调用过程,请使用 CALL、Java

如何在 PostgreSQL 13 中使用 INOUT 参数调用存储过程(不是函数)

Postgresql 9.2 中在查询中调用函数的正确方法

在 postgresql 中为每个更新的行调用一个函数