执行CallableStatement时没有返回任何内容

时间:2016-06-04 16:42:49

标签: java postgresql stored-procedures

调用一个不返回任何内容的函数时,我遇到了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;

1 个答案:

答案 0 :(得分:2)

不要使用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,则在字符串中使用占位符并将参数传递给execute函数。不要连接值:

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;