从PL / pgSQL函数返回行

我在PostgreSQL中有一个过程:

CREATE OR REPLACE FUNCTION get_geom_difference() RETURNS void AS $$ BEGIN SELECT filedata.num,st_area(ST_Difference(ST_TRANSFORM(filedata.the_geom,70066),filedata_temp.the_geom)) FROM filedata, filedata_temp Where filedata.num=filedata_temp.num end; $$ LANGUAGE 'plpgsql' 

我在Java中调用它并希望获得此过程的结果。 如何更改此过程以使结果成为可能? 以及如何在JDBC中使用它?

现在我用这个:

 Integer fileId; Class.forName("org.postgresql.Driver"); Connection connect= null; connect = DriverManager.getConnection("jdbc:postgresql://localhost:5432/postgis","postgres","123456"); java.sql.CallableStatement proc = connect.prepareCall("{?=call get_geom_difference()}"); proc.registerOutParameter(1, java.sql.Types.Integer); proc.execute(); ResultSet results = (ResultSet) proc.getObject(1); while (results.next()) { fileId=r.getInt("num"); } proc.close(); connect.close(); out.println(fileId); 

但是当我尝试在JDBC中调用该过程时,我得到了

错误org.apache.jasper.JasperException:在第25行处理JSP页面/commit_changes.jsp时发生exception

第25行是: proc.execute();

正确的function定义

 CREATE OR REPLACE FUNCTION get_geom_difference() RETURNS TABLE (num mumeric, my_area geometry) AS $BODY$ SELECT f.num ,st_area(ST_Difference(ST_TRANSFORM(f.the_geom, 70066), t.the_geom)) FROM filedata f JOIN filedata_temp t USING (num); $BODY$ LANGUAGE sql; 

您正在返回一个复合类型的SET(两列),您必须相应地声明该函数。 RETURNS TABLE是最方便的方法。

请确保对查询中的列名进行表限定,以使它们不与同名的OUT列冲突。

您可以使用language SQL函数进行此基本查询(或者您可以只执行原始SQL),不需要plpgsql。

在SQL中调用该函数

 SELECT * FROM get_geom_difference(); 

通过JDBC做到这一点

我在这里引用手册

不应通过CallableStatement接口调用将数据作为集合返回的函数,而应使用普通的Statement或PreparedStatement接口。

我也从网站上采用了这个例子并对其进行了调整:

 Statement stmt = conn.createStatement(); stmt.execute("  "); ResultSet rs = stmt.executeQuery("SELECT * FROM get_geom_difference();"); while (rs.next()) { // do something } rs.close(); stmt.close(); 

您也可以使用refcursor。 阅读手册中的更多内容 。

在您的定义中,您的函数返回任何RETURNS void 。 如果你想要num数据类型只需更改为RETURNS numeric 。 另外,要使其工作,请执行select到一些数值变量SELECT INTO var并将return var添加到函数的末尾。

虽然Erwin提供了一个很好的答案,但我想我会分享一个函数采用params的版本,并且我在函数体内使用了新的postgres返回查询语法。 不同之处在于它似乎设置了params,你必须使用PreparedStatement接口而不是更高级别的Statement。 这是我的pgfunction

 CREATE OR REPLACE FUNCTION gettools(_userid bigint) RETURNS table(id bigint,itemname character varying(250)) AS $BODY$ begin return query select distinct a.id, a.itemname from tool a inner join tooltie b on a.id = b.toolid and b.userid=_userid; end; $BODY$ LANGUAGE plpgsql STABLE COST 100; 

这是我的java,只是用数据填充地图

  private static final String GET_DATASOURCES = "select * from getdatasources(?)"; public Map getAuthDataSources(Long userid) { Map auths = new TreeMap<>(); try { if (connection == null || connection.isClosed()) { init(); } PreparedStatement cs = connection.prepareStatement(GET_DATASOURCES); // this is where to set the param ? for the function cs.setLong(1, userid); connection.setAutoCommit(false); ResultSet result = cs.executeQuery(); while (result.next()) { Long id = result.getLong(1); String itemname = result.getString(2); auths.put(id, itemname); } cs.close(); connection.commit(); connection.setAutoCommit(true); connection.close(); } catch (SQLException ex) { LOG.error("error getting data sources", ex); } return auths; } 

希望这有助于某人。