Question

I'm using PostgreSQL and I have a function that returns a record:

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 

I call it with this, because I must declare the type of the out values, that works fine in 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)

But to call this in a callableStatement in java I use:

proc = this.cn.prepareCall("{call fn_lisMatricula()}")

But I get a postgreSQL.exception:

the list of definition of columns is required to functions that returns «record»

So I temporarily solved this in Java using a preparedStatement:

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

I want to use a callableStatement. How can I do this?

Was it helpful?

Solution

I solve it, with this ... i read some from create table clause ... thanks =)

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

OTHER TIPS

SQL demands to know the return type at the time a statement is called. If you declare your return type as anonymous record, you have to provide a column definition list with every call. Very unwieldy.
Declare the return type in the function instead.

Here is a closely related answer with all the details:
PostgreSQL: ERROR: 42601: a column definition list is required for functions returning "record"

And here is some advanced black magic for various semi-dynamic return types:
Refactor a PL/pgSQL function to return the output of various SELECT queries

To be clear: the definition of the return type works the same way with PL/pgSQL and SQL functions.

Query

This could really just be an SQL function, that's simpler:

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;
  • Note that column aliases in the function body are just noise. They are discarded in favor of the names in the RETURN type. Only the position of the column is relevant. I left the aliases as comments for documentation.

  • My standsing advice is not to use CamelCase identifiers with PostgreSQL. When not surrounded by double-quotes they are folded to lower case.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top