Ir al contenido


Foto

Dinamizar un Procedimiento Almacenado


  • Por favor identifícate para responder
8 respuestas en este tema

#1 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 21 noviembre 2012 - 06:11

Pues eso, quiero dinamizar un procedimiento almacenado que tengo ya existente, por ejemplo, ahora mismo tengo el mismo select del SP en una consulta (O sea, no el SP mismo, sino una consulta normal) en un IBQuery y en un Formulario, y a través de ese formulario dinamizo la consulta de acuerdo a la selección del usuario, ordenar por un campo específico, filtrar los datos por un valor determinado y la forma de ordenar (Asco Desc), todo eso quiero hacerlo dentro del SP ya sea como parámetro de entrada o de otro modo, la verdad es que soy bastante verde con esto de los SP's, el objetivo de esto es poder aprovechar la potencia del motor, si es necesario coloco el SP que tengo:

CREATE OR ALTER PROCEDURE LIST_VEHICULOS 
returns (
    sid integer,
    sficha varchar(10),
    smarca varchar(20),
    smodelo varchar(30),
    splaca varchar(10),
    scolor varchar(20),
    sanio integer,
    sasignado varchar(60),
    scomb varchar(15),
    stipo varchar(50),
    sestado integer)
as
declare variable vid integer;
declare variable vficha varchar(10);
declare variable vmarca varchar(20);
declare variable vmodelo varchar(30);
declare variable vplaca varchar(10);
declare variable vcolor varchar(20);
declare variable vanio integer;
declare variable vasignado varchar(60);
declare variable vcomb varchar(15);
declare variable vtipo varchar(50);
declare variable vestado integer;
BEGIN
        FOR SELECT V.VE_ID, V.VE_FICHA, V.VE_MARCA, V.VE_MODELO, V.VE_PLACA, V.VE_COLOR, V.VE_ANIO,
            V.VE_ASIGNADOA, C.COMB_NOMBRE, T.TV_NOMBRE, A.AS_ESTADO FROM VEHICULOS V
            LEFT JOIN COMBUSTIBLES C ON C.comb_id = V.comb_id
            LEFT join TIPOS_VEHICULOS T ON T.tv_id = V.ve_tipo
            LEFT JOIN asignacion A ON A.ve_id = V.ve_id
        INTO :VID, :VFICHA, :VMARCA, :VMODELO,
              :VPLACA, :VCOLOR, :VANIO, :VASIGNADO,
              :VCOMB, VTIPO, VESTADO DO
        BEGIN
            SID = :VID;
            SFICHA = :VFICHA;
            SMARCA = :VMARCA;
            SMODELO = :VMODELO;
            SPLACA = :VPLACA;
            SCOLOR = :VCOLOR;
            SANIO = :VANIO;
            SASIGNADO = :VASIGNADO;
            SCOMB = :VCOMB;
            STIPO = :VTIPO;
            SESTADO = :VESTADO;
            SUSPEND;
        END
    END


Saludos.
  • 0

#2 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.092 mensajes
  • LocationRepública Dominicana

Escrito 21 noviembre 2012 - 06:30

Saludos.

Para eso tienes Execute Statement.
  • 0

#3 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 21 noviembre 2012 - 07:05

Saludos.

Para eso tienes Execute Statement.


Gracias mi estimado, la verdad que leyendo no entendí, y buscando los ejemplos no vi nada a lo que busco así que no pude entender el uso del EXECUTE STATEMENT, Perdón  :
  • 0

#4 cadetill

cadetill

    Advanced Member

  • Moderadores
  • PipPipPip
  • 994 mensajes
  • LocationEspaña

Escrito 21 noviembre 2012 - 07:50

Buenas

Su uso es sencillo. Tu montas una cadena con la sentencia SQL que quieras lanzar y luego, con el comando, la lanzas. Un ejemplo de una aplicación real:

ALTER PROCEDURE ANALISIS_PROD (
    CAMPO INTEGER,
    AFIELD VARCHAR(50),
    AVALUE VARCHAR(51),
    AVALUE2 VARCHAR(200))
RETURNS (
    PARTIDA NUMERIC(18,3),
    ALBARANES NUMERIC(18,3),
    VALORADA NUMERIC(18,3),
    COSTEPREV NUMERIC(18,3))
AS
declare variable sql varchar(1000);
begin
    /* *************************************************************************
    procedimiento almacenado que calculará los valores del análisis de producción

    Parámetros de entrada:
      - CAMPO: define el criterio de selección.
            0: por PARTIDA
            1: por EMPRESA
            2: por ACTIVIDAD
    ************************************************************************* */

    /* cálculo de la partida */
    SQL = 'select sum(p.imes) from produccion p ';
    if (campo <> 0) then
        SQL = SQL || '    left outer join descomplanidire d on d.capiobra = p.capiobra and d.partida = p.partida and d.codprod = p.codprod ';

    SQL = SQL || 'where p.' || :afield || ' = ''' || :avalue || ''' ';
   
    if (campo = 1) then
        SQL = SQL || '  and d.cifempresa = ''' || :avalue2 || ''' ';
    if (campo = 2) then
        SQL = SQL || '  and d.actividad = ''' || :avalue2 || ''' ';

    execute statement SQL into :partida;

    /* cálculo de los albaranes */
    select sum(impmes) from analisis_prod_alb(:campo, :afield, :avalue, :avalue2)
    into :albaranes;

    /* cálculo de las valoradas */
    select sum(impmes) from analisis_prod_valo(:campo, :afield, :avalue, :avalue2)
    into :valorada;

    /* cálculo del Coste Previsto */
    SQL = 'select sum(p.cmes) from produccion p ';
    if (campo <> 0) then
        SQL = SQL || '    left outer join descomplanidire d on d.capiobra = p.capiobra and d.partida = p.partida and d.codprod = p.codprod ';

    SQL = SQL || 'where p.' || :afield || ' = ''' || :avalue || ''' ';
   
    if (campo = 1) then
        SQL = SQL || '  and d.cifempresa = ''' || :avalue2 || ''' ';
    if (campo = 2) then
        SQL = SQL || '  and d.actividad = ''' || :avalue2 || ''' ';

    execute statement SQL into :costeprev;

  suspend;
end^


Además, puedes usarlo en un for ... do para devolver más de una fila

Espero haberte ayudado

Nos leemos

  • 0

#5 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 21 noviembre 2012 - 08:00

Ah! Muchas gracias Cadetill, ahora con ese ejemplo ya entedí el uso del EXECUTE STATEMENT, ya lo pondré en práctica, Gracias a ambos.

Saludos.
  • 0

#6 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 21 noviembre 2012 - 09:27

A la primera me salió perfecto, todo funciona correctamente, de nuevo, muchas gracias a ambos, las cosa quedó así:

CREATE OR ALTER PROCEDURE LIST_VEHICULOS (
    orden varchar(1),
    filtro integer,
    campo varchar(25))
returns (
    sid integer,
    sficha varchar(10),
    smarca varchar(20),
    smodelo varchar(30),
    splaca varchar(10),
    scolor varchar(20),
    sanio integer,
    sasignado varchar(60),
    scomb varchar(15),
    stipo varchar(50),
    sestado integer)
as
declare variable sql varchar(1000);
declare variable vid integer;
declare variable vficha varchar(10);
declare variable vmarca varchar(20);
declare variable vmodelo varchar(30);
declare variable vplaca varchar(10);
declare variable vcolor varchar(20);
declare variable vanio integer;
declare variable vasignado varchar(60);
declare variable vcomb varchar(15);
declare variable vtipo varchar(50);
declare variable vestado integer;
BEGIN
    SQL = 'SELECT V.VE_ID, V.VE_FICHA, V.VE_MARCA, V.VE_MODELO, V.VE_PLACA, V.VE_COLOR, V.VE_ANIO,
            V.VE_ASIGNADOA, C.COMB_NOMBRE, T.TV_NOMBRE, A.AS_ESTADO FROM VEHICULOS V
            LEFT JOIN COMBUSTIBLES C ON C.comb_id = V.comb_id
            LEFT join TIPOS_VEHICULOS T ON T.tv_id = V.ve_tipo
            LEFT JOIN asignacion A ON A.ve_id = V.ve_id';

    if (filtro > 0) then
        SQL = SQL || ' where A.AS_ESTADO = ' || :FILTRO;

    if (CAMPO <> '') then
        SQL = SQL || ' ORDER BY ' || :campo;

    if (ORDEN = 'A') then
        SQL = SQL || ' ASC';

    if (ORDEN = 'D') then
        SQL = SQL || ' DESC';

    FOR EXECUTE statement SQL INTO :VID, :VFICHA, :VMARCA, :VMODELO,
              :VPLACA, :VCOLOR, :VANIO, :VASIGNADO,
              :VCOMB, VTIPO, VESTADO DO
        BEGIN
            SID = :VID;
            SFICHA = :VFICHA;
            SMARCA = :VMARCA;
            SMODELO = :VMODELO;
            SPLACA = :VPLACA;
            SCOLOR = :VCOLOR;
            SANIO = :VANIO;
            SASIGNADO = :VASIGNADO;
            SCOMB = :VCOMB;
            STIPO = :VTIPO;
            SESTADO = :VESTADO;
            SUSPEND;
        END
    END


Saludos.
  • 0

#7 cadetill

cadetill

    Advanced Member

  • Moderadores
  • PipPipPip
  • 994 mensajes
  • LocationEspaña

Escrito 21 noviembre 2012 - 10:01

Y no sería algo más sencillo así??

CREATE OR ALTER PROCEDURE LIST_VEHICULOS (
    orden VARCHAR(1),
    filtro INTEGER,
    campo VARCHAR(25))
RETURNS (
    sid INTEGER,
    sficha VARCHAR(10),
    smarca VARCHAR(20),
    smodelo VARCHAR(30),
    splaca VARCHAR(10),
    scolor VARCHAR(20),
    sanio INTEGER,
    sasignado VARCHAR(60),
    scomb VARCHAR(15),
    stipo VARCHAR(50),
    sestado INTEGER)
AS
DECLARE variable SQL VARCHAR(1000);
BEGIN
    SQL = 'SELECT V.VE_ID, V.VE_FICHA, V.VE_MARCA, V.VE_MODELO, V.VE_PLACA, V.VE_COLOR, V.VE_ANIO,
          V.VE_ASIGNADOA, C.COMB_NOMBRE, T.TV_NOMBRE, A.AS_ESTADO FROM VEHICULOS V
          LEFT JOIN COMBUSTIBLES C ON C.comb_id = V.comb_id
          LEFT join TIPOS_VEHICULOS T ON T.tv_id = V.ve_tipo
          LEFT JOIN asignacion A ON A.ve_id = V.ve_id';
   
    IF (filtro > 0) THEN
        SQL = SQL || ' where A.AS_ESTADO = ' || :FILTRO;
   
    IF (CAMPO <> '') THEN
        SQL = SQL || ' ORDER BY ' || :campo;
   
    IF (ORDEN = 'A') THEN
        SQL = SQL || ' ASC';
   
    IF (ORDEN = 'D') THEN
        SQL = SQL || ' DESC';
   
    FOR EXECUTE statement SQL INTO :SID, :SFICHA, :SMARCA, :SMODELO,
              :SPLACA, :SCOLOR, :SANIO, :SASIGNADO,
              :SCOMB, :STIPO, :SESTADO DO
    BEGIN
      SUSPEND;
    END
END


Quizás quede más sencillo y legible ;)

Nos leemos

  • 0

#8 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 21 noviembre 2012 - 10:26

Pues si pudiera lo haría, no sé por qué en IBExpert me marca errores sino ponía variables de esa forma :s
  • 0

#9 cadetill

cadetill

    Advanced Member

  • Moderadores
  • PipPipPip
  • 994 mensajes
  • LocationEspaña

Escrito 21 noviembre 2012 - 11:24

Qué errores te marca? Porque eso debería de funcionarte :(

Acabo de probarlo en FB 2.5 y no me da ningún problema :(
  • 0




IP.Board spam blocked by CleanTalk.