如何返回 callableStatement 结果?
Posted
技术标签:
【中文标题】如何返回 callableStatement 结果?【英文标题】:How to return a callableStatement result? 【发布时间】:2013-04-03 22:06:07 【问题描述】:我正在使用 PostgreSQL,并且我有一个返回记录的函数:
CREATE OR REPLACE FUNCTION fn_lisMatricula()
RETURNS record AS
$BODY$
SELECT mat.codigo as codmatr, mat.codigoalumno as codal, mat.codigoempresa as codemp ,mat.codigopresentacion as codpre,
mat.codigosecretaria as codsec, mat.fecha as fechamat, mat.estado as estadomat,
mat.vigencia as vigmat, p.apellidos as apeAl,
p.nombres as nomAl,razonsocial ,pre.codigocurso as codcur,cur.nombre as curso
FROM matricula mat join alumno al on mat.codigoalumno = al.codigoalumno
join persona p on al.codigoalumno = p.codigo
join persona pe on mat.codigoalumno = pe.codigo
left join empresa emp on mat.codigoempresa = emp.codigo
join presentacion pre on mat.codigopresentacion = pre.codigo
join curso cur on cur.codigo = pre.codigocurso
order by p.apellidos
$BODY$
LANGUAGE sql VOLATILE
我用这个来称呼它,因为我必须声明输出值的类型,这在 Postgres 中可以正常工作:
select * from fn_lisMatricula() as (codmatr integer,codal integer,codemp integer,codpre integer,codsec integer,fechamat date,
estadomat char,vigmat boolean,apeal varchar,nomal varchar,razonsocial varchar,codcur integer,curso varchar)
但是要在 java 中的 callableStatement 中调用它,我使用:
proc = this.cn.prepareCall("call fn_lisMatricula()")
但我得到一个 postgreSQL.exception:
返回«record»的函数需要列的定义列表
所以我使用preparedStatement在Java中临时解决了这个问题:
PreparedStatement ps;
String SQL = "select * from fn_lisMatricula() as (codmatr integer,codal integer,codemp integer,codpre integer,codsec integer,fechamat date,\n"
+ "estadomat char,vigmat boolean,apeal varchar,nomal varchar,razonsocial varchar,codcur integer,curso varchar)";
ps = this.cn.prepareStatement(SQL);
我想使用 callableStatement。我该怎么做?
【问题讨论】:
【参考方案1】:我解决了这个问题……我从 create table 子句中读到了一些……谢谢=)
CREATE OR REPLACE FUNCTION fn_lisMatricula()
RETURNS TABLE (codmatr integer,codal integer,codemp integer,codpre integer,codsec integer,fechamat date,
estadomat char,vigmat boolean,apeal varchar,nomal varchar,razonsocial varchar,codcur integer,curso varchar) AS
$BODY$
BEGIN
RETURN QUERY
SELECT mat.codigo as codmatr, mat.codigoalumno as codal, mat.codigoempresa as codemp ,mat.codigopresentacion as codpre,
mat.codigosecretaria as codsec, mat.fecha as fechamat, mat.estado as estadomat,
mat.vigencia as vigmat, p.apellidos as apeAl,
p.nombres as nomAl,emp.razonsocial ,pre.codigocurso as codcur,cur.nombre as curso
FROM matricula mat join alumno al on mat.codigoalumno = al.codigoalumno
join persona p on al.codigoalumno = p.codigo
join persona pe on mat.codigoalumno = pe.codigo
left join empresa emp on mat.codigoempresa = emp.codigo
join presentacion pre on mat.codigopresentacion = pre.codigo
join curso cur on cur.codigo = pre.codigocurso
order by p.apellidos;
END
$BODY$
LANGUAGE plpgsql;
select * from fn_lisMatricula()
【讨论】:
我在回答中添加了对您的功能的评论。【参考方案2】:SQL 要求在调用语句时知道返回类型。如果将返回类型声明为匿名记录,则必须在每次调用时提供列定义列表。非常笨拙。 而是在函数中声明返回类型。
这是一个包含所有细节的密切相关的答案:PostgreSQL: ERROR: 42601: a column definition list is required for functions returning "record"
这里有一些用于各种半动态返回类型的高级黑魔法:Refactor a PL/pgSQL function to return the output of various SELECT queries
明确一点:返回类型的定义与 PL/pgSQL 和 SQL 函数的工作方式相同。
查询
这可能真的只是一个SQL function,这更简单:
CREATE OR REPLACE FUNCTION fn_lis_matricula()
RETURNS TABLE (
codmatr integer
, codal integer
, codemp integer
, codpre integer
, codsec integer
, fechamat date
, estadomat char
, vigmat boolean
, apeal varchar
, nomal varchar
, razonsocial varchar
, codcur integer
, curso varchar) AS
$BODY$
SELECT mat.codigo -- as codmatr
, mat.codigoalumno -- as codal
, mat.codigoempresa -- as codemp
, mat.codigopresentacion -- as codpre
, mat.codigosecretaria -- as codsec
, mat.fecha -- as fechamat
, mat.estado -- as estadomat
, mat.vigencia -- as vigmat
, p.apellidos -- as apeAl
, p.nombres -- as nomAl
, emp.razonsocial
, pre.codigocurso -- as codcur
, cur.nombre -- as curso
FROM matricula mat
JOIN alumno al ON mat.codigoalumno = al.codigoalumno
JOIN persona p ON al.codigoalumno = p.codigo
JOIN persona pe ON mat.codigoalumno = pe.codigo
JOIN presentacion pre ON mat.codigopresentacion = pre.codigo
JOIN curso cur ON cur.codigo = pre.codigocurso
LEFT JOIN empresa emp ON mat.codigoempresa = emp.codigo
ORDER BY p.apellidos;
$BODY$
LANGUAGE sql;
请注意,函数体中的列别名只是噪音。它们被丢弃,取而代之的是 RETURN
类型中的名称。只有列的位置是相关的。我将别名作为 cmets 留作文档。
我的一贯建议是不要在 PostgreSQL 中使用 CamelCase 标识符。当没有被双引号包围时,它们被折叠成小写。
【讨论】:
感谢我阅读了您的一些链接,我从退货表条款中阅读了更多内容,我解决了,谢谢以上是关于如何返回 callableStatement 结果?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 Java JDBC 中的 callableStatement 获取滚动不敏感的结果集?
Java Callablestatement 不会等到 .execute() 结束
CallableStatement + registerOutParameter + 多行结果