【问题标题】:A CallableStatement was executed with nothing returned执行了 CallableStatement,但没有返回任何内容
【发布时间】:2016-06-04 16:42:49
【问题描述】:

调用不返回任何内容的函数时出现 Java 异常:

org.postgresql.util.PSQLException: A CallableStatement was executed with nothing returned.

Java 代码类似这样:

// Procedure call.
CallableStatement proc = con.prepareCall("{ ? = call doquery ( ? ) }");
proc.registerOutParameter(1, Types.Other);
proc.setInt(2, 33434);
proc.execute();
ResultSet results = (ResultSet) proc.getObject(1);
while (results.next()) {
  // do something with the results...
}
results.close();
proc.close();

查询很简单:

select * from table where idTable = 33434;

查询不返回任何值,因为我在 postgresql DB 中查找的内容不存在。一个 sql 查询就是这样,我们并不总是得到一些回报。

你如何处理这种情况?

PS.- Postgresql 函数:

CREATE OR REPLACE FUNCTION doquery(_idTable bigint)
  RETURNS TABLE(idTable bigint, name varchar) AS
$BODY$
DECLARE
    searchsql text := '';
BEGIN
    searchsql := 'SELECT * FROM table
            WHERE idTable = ' || _idTable;

    RETURN QUERY EXECUTE searchsql;
END
$BODY$
  LANGUAGE plpgsql;

【问题讨论】:

  • 显示使用你的存储过程,你需要确保你的存储过程返回一些东西
  • 我已经附加了存储过程!
  • 我不明白为什么你需要一个存储过程来做这样一个简单的查询,你能澄清一下吗?
  • 这只是一个实验,我需要的是一个复杂的动态查询。如果这个简单的例子行不通,我该怎么做一个复杂的任务呢?那将是浪费时间!

标签: java postgresql stored-procedures


【解决方案1】:

不要使用 CallableStatement。它们适用于存储的过程,而不是函数。

当您的函数返回结果集时,您需要使用select 语句:

PreparedStatement pstmt = con.prepareStatement("select * from doquery(?)");
pstmt.setInt(1, 33434);

ResultSet results = pstmt.executeQuery();
while (results.next()) {
  // do something with the results...
}
results.close();
proc.close();

请注意,不需要使用动态 SQL 甚至 PL/pgSQL。您也不应该将参数附加到查询中(就像在 Java 中不应该这样做一样)。使用参数占位符:

CREATE OR REPLACE FUNCTION doquery(_idTable bigint)
  RETURNS TABLE(idTable bigint, name varchar) AS
$BODY$
BEGIN
    RETURN QUERY 
       SELECT * 
       FROM table
       WHERE idTable = _idTable;
END
$BODY$
  LANGUAGE plpgsql;

或者更简单的纯 SQL 函数:

CREATE OR REPLACE FUNCTION doquery(_idTable bigint)
  RETURNS TABLE(idTable bigint, name varchar) AS
$BODY$
   SELECT idtable, name 
   FROM table
   WHERE idTable = _idTable;
$BODY$
  LANGUAGE sql;

如果您确实需要动态 SQL,则在字符串中使用占位符并将参数传递给执行函数。不要连接值:

CREATE OR REPLACE FUNCTION doquery(_idTable bigint)
  RETURNS TABLE(idTable bigint, name varchar) AS
$BODY$
BEGIN
    RETURN QUERY EXECUTE '
       SELECT * 
       FROM table
       WHERE idTable = $1'
    USING _idTable;
END
$BODY$
  LANGUAGE plpgsql;

【讨论】:

  • 如果不应使用 CallableStatement,因为它不适用于函数。如果你正在使用一个函数,你应该怎么做?我知道这个示例返回一个结果集,在这种情况下,选择语句可能会更好。这个 Postgres 文档建议在使用函数时使用可调用语句; jdbc.postgresql.org/documentation/head/callproc.html
  • @Martin:不是“可能更好”,但肯定更好(对于返回结果集的函数)驱动程序手册中带有可调用语句的示例用于标量函数(返回单个值)。为他们使用你喜欢的任何东西。
猜你喜欢
  • 2021-09-24
  • 1970-01-01
  • 2020-04-16
  • 2018-07-30
  • 2011-04-01
  • 2016-06-23
  • 2018-04-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多