Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   SQL (https://www.clubdelphi.com/foros/forumdisplay.php?f=6)
-   -   Cómo usar variables en lugar de campos (https://www.clubdelphi.com/foros/showthread.php?t=71431)

Casimiro Notevi 18-12-2010 02:06:12

Cómo usar variables en lugar de campos
 
Hola, tengo una duda con la sintaxis sql en firebird, concretamente para los triggers, aunque supongo que será igual para "store procedure".

Explico el problema con un ejemplo:

Tabla....: tbSaldosApuntes
Campos...: debe1,haber1,debe2,haber2,debe3,haber3, ... debe12,haber12
Trigger..:

Código SQL [-]
declare variable iMes integer;

select 'debe'||cast(iMes as varchar2) from tbsaldosapuntes where...


Es sólo un ejemplo, pero más o menos es lo que quiero conseguir, no tener que repetir algo porque cambia sólo el número (de mes, en este caso).

Creo que se entiende.

Me parece recordar que en algún hilo se habló sobre ese tema y que era posible hacerlo, pero no lo he encontrado.

Gracias y...

celades1 18-12-2010 10:25:34

Hola

A partir de firebird 2.0 tienes el execute statement
yo lo utilizo para solucionar problemas parecido al que planteas



Código SQL [-]
CREATE PROCEDURE NEW_PROCEDURE 
returns (debe double precision)
as
declare variable imes integer;
declare variable cadena varchar(500);
begin
 imes=1;
  while (:imes<13) do begin
  cadena='select debe'||cast(imes as varchar(12))||' from tbsaldosapuntes'||
  ' where lo que sea' 
  execute statement cadena into :debe;
  suspend;
  imes=:imes+1;
  end
end


Saludos

Luis M. 18-12-2010 12:48:00

Hola.
No se si te servirá esto, yo lo utilizo para saber la última línea de un detalle de una tabla cualquiera, según el parámetro que le paso.

Código Delphi [-]
SET TERM ^ ;

create or alter procedure ULTIMA_LINEA (
    CAMPO_LINEA varchar(15),
    TABLA varchar(15),
    CAMPO_DOCU varchar(15),
    NUMERO_DOCU varchar(15))
returns (
    ULTIMA varchar(10))
as
begin
  /* Procedure Text */
  EXECUTE STATEMENT 'SELECT max('||:campo_linea||') FROM '||:tabla||' where '
                    ||:campo_docu||' = '||:numero_docu INTO :ultima;
  suspend;
end^

SET TERM ; ^

GRANT EXECUTE ON PROCEDURE ULTIMA_LINEA TO SYSDBA;

Un saludo.

Casimiro Notevi 18-12-2010 12:49:20

Muchísimas gracias, me habéis salvado de un montón de horas de trabajo repetitivo y pesado.
Todos los días se aprende algo, voy a probarlo ahora mismo... :)

fjcg02 18-12-2010 15:34:53

Aunque ya te han contestado ( y muy bien por cierto), yo suelo utilizar consultas de este tipo, que me han proporcionado muchas satisfacciones ante mis clientes.
Tienes meses, trimestres o lo que quieras.
Lógicamente, hay que preparar las agrupaciones, filtrar por fechas, ... pero el esqueleto es más que aprovechable. Y dándole una vuelta, se pueden conseguir resultados muy chulos.

Código SQL [-]
select
SUM(case when extract(month from loga) = 1 then PRIMARECIBO else 0 end) AS ENERO,
SUM(case when extract(month from loga) = 2 then PRIMARECIBO else 0 end) AS FEBRERO,
SUM(case when extract(month from loga) = 3 then PRIMARECIBO else 0 end) AS MARZO,
SUM(case when extract(month from loga) = 4 then PRIMARECIBO else 0 end) AS ABRIL,
SUM(case when extract(month from loga) = 5 then PRIMARECIBO else 0 end) AS MAYO,
SUM(case when extract(month from loga) = 6 then PRIMARECIBO else 0 end) AS JUNIO,
SUM(case when extract(month from loga) = 7 then PRIMARECIBO else 0 end) AS JULIO,
SUM(case when extract(month from loga) = 8 then PRIMARECIBO else 0 end) AS AGOSTO,
SUM(case when extract(month from loga) = 9 then PRIMARECIBO else 0 end) AS SEPTIEMBRE,
SUM(case when extract(month from loga) = 10 then PRIMARECIBO else 0 end) AS OCTUBRE,
SUM(case when extract(month from loga) = 11 then PRIMARECIBO else 0 end) AS NOVIEMBRE,
SUM(case when extract(month from loga) = 12 then PRIMARECIBO else 0 end) AS DICIEMBRE,
SUM(case when
          (extract(month from loga) >= 1 AND extract(month from loga) <= 3)
          then PRIMARECIBO else 0 end) AS TRIMESTRE1,
SUM(case when
          (extract(month from loga) >= 4 AND extract(month from loga) <= 6)
          then PRIMARECIBO else 0 end) AS TRIMESTRE2,
SUM(case when
          (extract(month from loga) >= 7 AND extract(month from loga) <= 9)
          then PRIMARECIBO else 0 end) AS TRIMESTRE3,
SUM(case when
          (extract(month from loga) >= 10 AND extract(month from loga) <= 12)
          then PRIMARECIBO else 0 end) AS TRIMESTRE4

from  RECIBO

Un saludo

Casimiro Notevi 18-12-2010 16:54:42

Gracias, muy interesante.

Casimiro Notevi 18-12-2010 21:12:20

Pues he estado probando y no me funciona, no sé si no vale para los triggers, aunque no da error ninguno, simplemente no se ejecuta.
He probado a guardar la sentencia creada en una tabla tbDebug y es correcta, así que no lo entiendo porque el código "normal" sí que funciona, lo he puesto al final, en comentario.
¿Podéis hacer una pruebecita con triggers en lugar de store procedure?
Estoy usando firebird 2.1

Código SQL [-]
CREATE OR ALTER trigger tbapuntes_ai0 for tbapuntes
active after insert position 0
AS
  declare variable iMes integer;
  declare variable cCampoDebe  varchar(8);
  declare variable cCampoHaber varchar(8);
  declare variable cSql        varchar(1024);
begin
  /* actualizar tbSaldosCuentas */
  if (new.codigoborrador>0) then  /* es borrador */
  begin
    update tbSaldosCuentas
    set debetotal=debetotal+new.debe,
        habertotal=habertotal+new.haber
    where codigoempresa=codigoempresa
    and ejercicio=ejercicio
    and codigocuenta=codigocuenta;
  end
  else /* no es borrador, es definitivo */
  begin
    iMes = extract(month from new.fechaasiento);
    cCampoDebe  = 'debe'  || cast(iMes as varchar(2));
    cCampoHaber = 'haber' || cast(iMes as varchar(2));
    cSql = 'update tbsaldoscuentas ' ||
           'set debetotal=debetotal+new.debe, ' ||
           'habertotal=habertotal+new.haber, ' ||
           cCampoDebe  || '=' || cCampoDebe  || '+new.debe, ' ||
           cCampoHaber || '=' || cCampoHaber || '+new.haber ' ||
           'where codigoempresa=codigoempresa ' ||
           'and ejercicio=ejercicio ' ||
           'and codigocuenta=codigocuenta';
/* >>> debug >>> */
/* insert into tbdebug (texto) values (:csql); */
/* <<< debug <<< */
    execute statement cSql;
  end

/* esto funciona */
/*
    update tbsaldoscuentas
    set debetotal  = debetotal  + new.debe,
        habertotal = habertotal + new.haber,
        debe12  = debe12  + new.debe,
        haber12 = haber12 + new.haber
    where codigoempresa=codigoempresa
    and ejercicio=ejercicio
    and codigocuenta=codigocuenta;
*/
end

celades1 19-12-2010 10:43:22

Hola

Creo que el problema es que no tratas los new como variables

csql todo es varchar por ello debes convertir los new a varchar

Código SQL [-]
    cSql = 'update tbsaldoscuentas ' ||
           ' set debetotal=debetotal+'||cast(new.debe as varchar(15)) || ', ' ||
           'habertotal=habertotal+'||cast(new.haber as varchar(15)) || ', ' ||
           :cCampoDebe  || '=' || :cCampoDebe  || '+' || 
           cast(new.debe as varchar(15)) || ', ' ||
           :cCampoHaber || '=' || :cCampoHaber || '+'||
           cast(new.haber as varchar(15))||
           ' where codigoempresa=codigoempresa ' ||
           ' and ejercicio=ejercicio ' ||
           ' and codigocuenta=codigocuenta';



Pruba y ya me diras

La where no la entiendo pero eso ya es otro problema

Saludos

Panta

Casimiro Notevi 19-12-2010 12:20:31

Sí, gracias, celades1, ya me he dado cuenta, parece que al execute statement hay que darle todo bien "mascadito".
No sé si será mejor crear un store procedure que reciba el mes y punto. Haré pruebas a ver qué es más eficiente.

fjcg02 19-12-2010 15:36:51

Hola a todos,

el problema qyue estás planteando no es el mismo que me ocurrió en esta ocasión ??

http://www.clubdelphi.com/foros/show...cute+statement

Si no recuerdo mal, el problema es que el execute statement no puede resolver las variables new.campo y old.campo fuera del ámbito del store p. o del trigger.

No estoy del todo seguro de si estamos itentando hacer lo mismo... ( es que es domingo por la tarde , haceos cargo ).

Ya me direis, ...

Saludos y suerte

Casimiro Notevi 19-12-2010 15:44:11

Pues parece que sí, que es similar, el caso es que execute statement necesita la cadena completa, no se le puede pasar un campo para que obtenga el valor del mismo. En fin, no es muy práctico pero parece que va bien así:

Código SQL [-]
CREATE OR ALTER trigger tbapuntes_ai1 for tbapuntes
active after insert position 1
AS
  declare variable iMes integer;
  declare variable cCampoDebe  varchar(8);
  declare variable cCampoHaber varchar(8);
  declare variable cSql        varchar(1024);
  declare variable cValorDebe  varchar(18);
  declare variable cValorHaber varchar(18);
begin
  /* actualizar tbSaldosCuentas */
  if (new.codigoborrador>0) then  /* es borrador */
  begin
    update tbSaldosCuentas
    set debetotal=debetotal+new.debe,
        habertotal=habertotal+new.haber
    where codigoempresa=codigoempresa
    and ejercicio=ejercicio
    and codigocuenta=codigocuenta;
  end
  else /* no es borrador, es definitivo */
  begin
    iMes = extract(month from new.fechaasiento);
    cCampoDebe  = 'debe'  || cast(iMes as varchar(2));
    cCampoHaber = 'haber' || cast(iMes as varchar(2));
    cValorDebe  = cast(new.debe  as varchar(18));
    cValorHaber = cast(new.haber as varchar(18));

    cSql = 'update tbsaldoscuentas '||
           'set debetotal=debetotal+'||cValorDebe||
           ',habertotal=habertotal+'||cValorHaber||','||
           cCampoDebe  || '=' || cCampoDebe  || '+'||cValorDebe||','||
           cCampoHaber || '=' || cCampoHaber || '+'||cValorHaber||
           ' where codigoempresa='||cast(new.codigoempresa as varchar(18))||
           ' and ejercicio='||cast(new.ejercicio as varchar(18))||
           ' and codigocuenta='||''''||new.codigocuenta||'''';
/* --- debug --> */
/* insert into tbdebug (texto) values (:csql);*/
/* <-- debug --- */
    execute statement cSql;
  end
end


La franja horaria es GMT +2. Ahora son las 18:38:16.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi