Skip site navigation (1) Skip section navigation (2)

Re: Llamadas recursivas en funciones de Base de Datos

From: Gustavo Vaccaro <gustavo_vaccaro(at)fibertel(dot)com(dot)ar>
To: arpug(at)postgresql(dot)org
Subject: Re: Llamadas recursivas en funciones de Base de Datos
Date: 2011-02-16 13:06:44
Message-ID: 4D5BCBE4.203@fibertel.com.ar (view raw or flat)
Thread:
Lists: arpug
Disculpen que insista
¿pero alguien sabe porque me tira el error cuando uso una funcion en forma 
recurvisa?
el error

ERROR:  el cursor «c_ctamadre» ya está en uso
CONTEXT:  función PL/pgSQL «fn_acumuxcuenta» en la línea 23 en OPEN
función PL/pgSQL «fn_acumuxcuenta» en la línea 29 en asignación

aparentemente se produce porque la declaracion del cursor "c_ctamadre" sigue 
viva de una llamada de funcion a la otra, pero no se como hacerla privada de la 
funcion.

Si alguien me puede ayudar, se lo voy a agradecer.

Saludos

Gustavo J. Vaccaro
http://www.gjv.com.ar


El 11/02/2011 08:25 a.m., Gustavo Vaccaro escribió:
> Emanuel,
> Ya me di cuenta que funcionan distintas. Me costo unas cuantas horas la 
> migracion, pero valio la pena.
> Te paso el codigo completo de la funcion:
>
> CREATE OR REPLACE FUNCTION "public"."fn_acumuxcuenta" (
>   "arg_nroemp" integer,
>   "arg_nroserie" integer,
>   "arg_cuenta" char,
>   "arg_fecdes" date,
>   "arg_fechas" date,
>   "arg_dh" char
> )
> RETURNS numeric AS
> $body$
> declare c_monto decimal(15,2);
> declare s_recmov character(1);
> declare s_cuenta character(25);
> declare c_ctamadre no scroll cursor for select id_cuenta from
> plancta where id_nroemp = arg_nroemp and id_ctamadre = arg_cuenta and
> id_cuenta <> id_ctamadre order by id_cuenta asc;
> begin
>     c_monto=0;
>     select recmov into s_recmov from plancta where id_nroemp = arg_nroemp and 
> id_cuenta = arg_cuenta;
>     /* */
>     if s_recmov = 'S' then
>         select sum(case when arg_dh = 'D' then debe else haber end) into c_monto
>         from asiren,asicab where asiren.id_nroemp = arg_nroemp and
>         asiren.id_nroserie = arg_nroserie and asiren.id_cuenta = arg_cuenta and
>         asicab.fecha between(arg_fecdes) and(arg_fechas) and
>         asiren.id_nroemp = asicab.id_nroemp and asiren.id_nroserie = 
> asicab.id_nroserie and
>         asiren.id_nroasi = asicab.id_nroasi and asicab.anulado = 'N';
>         /**/
>         if c_monto is null then
>             c_monto=0;
>         end if;
>     else
>         open c_ctamadre;
>         loop
>             fetch next from c_ctamadre into s_cuenta;
>             if not found then
>                 exit;
>             end if;
>             
> c_monto=c_monto+fn_acumuxcuenta(arg_nroemp,arg_nroserie,s_cuenta,arg_fecdes,arg_fechas,arg_dh);
>         end loop;
>         close c_ctamadre;
>     end if;
>     /* */
>        return(c_monto);
> end
> $body$
> LANGUAGE 'plpgsql'
> VOLATILE
> CALLED ON NULL INPUT
> SECURITY INVOKER
> COST 100;
>
> Saludos
>
> Gustavo J. Vaccaro
> http://www.gjv.com.ar
>
>
> El 10/02/2011 01:06 p.m., Emanuel Calvo Franco escribió:
>> El día 10 de febrero de 2011 15:06, Gustavo Vaccaro
>> <gustavo_vaccaro(at)fibertel(dot)com(dot)ar>  escribió:
>>> Hola,
>>> tengo una funcion (fn_acumuxcuenta) en postgres 8.4 que hace una llamada
>>> recursiva a si misma.
>>>
>>> *** FUNCION fn_acumuxcuenta *****
>>> declare c_monto decimal(15,2);
>>> declare c_ctamadre scroll cursor for select id_cuenta from
>>> plancta where id_nroemp = arg_nroemp and id_ctamadre = arg_cuenta and
>>> id_cuenta<>  id_ctamadre order by id_cuenta asc;
>>> BEGIN
>>> .....
>>> *** mas codigo ****
>>> .....
>>> linea 23:    open c_ctamadre;
>>>                    loop
>>>                    fetch next from c_ctamadre into s_cuenta;
>>>                    if not found then
>>>                       exit;
>>>                    end if;
>>> linea 29:
>>>   c_monto=c_monto+fn_acumuxcuenta(arg_nroemp,arg_nroserie,s_cuenta,arg_fecdes,arg_fechas,arg_dh);
>>>                    end loop;
>>>                    close c_ctamadre;
>>>
>>>                    return(c_monto);
>>> END
>>>
>>> Esta funcion la utilizo en una vista para que me devuelva el monto total
>>> acumulado.
>>> Cuando ejecuto la vista me tira el siguiente error:
>>>
>>>
>>> ERROR:  el cursor «c_ctamadre» ya está en uso
>>> CONTEXT:  función PL/pgSQL «fn_acumuxcuenta» en la línea 23 en OPEN
>>> función PL/pgSQL «fn_acumuxcuenta» en la línea 29 en asignación
>>>
>>> ********** Error **********
>>>
>>> ERROR: el cursor «c_ctamadre» ya está en uso
>>> Estado SQL:42P03
>>> Contexto:función PL/pgSQL «fn_acumuxcuenta» en la línea 23 en OPEN
>>> función PL/pgSQL «fn_acumuxcuenta» en la línea 29 en asignación
>>>
>>> Agradeceria alguna ayuda para intentar solucionar el problema.
>>>
>>> La funcion proviene de una migracion de Sybase Adaptive Server Anywhere y la
>>> recusividad funcionaba perfecto.
>>>
>> Pero ambas bases funcionan totalmente distintas respecto al manejo de cursores.
>>
>> Podrías pegar más detalles del código? Quizás se pueda implementar de
>> otra manera....
>>
>>
>>
>>

In response to

Responses

arpug by date

Next:From: Emanuel Calvo FrancoDate: 2011-02-16 13:16:01
Subject: Re: Llamadas recursivas en funciones de Base de Datos
Previous:From: Alejandro BrustDate: 2011-02-14 19:15:52
Subject: genexus y lock exclusive mode

Privacy Policy | About PostgreSQL
Copyright © 1996-2014 The PostgreSQL Global Development Group