Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Conexión con bases de datos (https://www.clubdelphi.com/foros/forumdisplay.php?f=2)
-   -   problemas al pasar un código SQL al selectSQL (https://www.clubdelphi.com/foros/showthread.php?t=4501)

Giniromero 17-10-2003 18:33:40

problemas al pasar un código SQL al selectSQL
 
Hola,

Uso delphi 6, interbase 7, dialecto3.

Estoy intentando usar el siguiente código SQL, en un IBDataSet.


Cita:

select NUMALU,SUM(0 - econo.impdebe + econo.imphaber) IMPORTE
from econo
WHERE NUMALU =:alumnos.numalu
GROUP BY NUMALU
ORDER BY NUMALU

Se lo estoy intentando pasar de la siguiente forma:

Cita:

TRY
dbPos := FrmDmodule.TbEcono.Getbookmark;
FrmDmodule.TbEcono.Disablecontrols;
FrmDModule.TbEcono.Close;
//borramos el contenido de la propiedad SelectSQL
FrmDModule.TbEcono.SelectSQL.Clear;
//le asignamos el SQL que tenía al inicio la tabla
FrmDModule.TbEcono.SelectSQL.Add('select NUMCLI, SUM(0 - econo.impdebe + econo.imphaber) IMPORTE');
FrmDModule.TbEcono.SelectSQL.Add('from econo');
FrmDModule.TbEcono.SelectSQL.Add('WHERE NUMCLI =:NUMCLI’);
FrmDModule.TbEcono.SelectSQL.Add('GROUP BY NUMCLI’);
FrmDModule.TbEcono.SelectSQL.Add('ORDER BY NUMCLI ');
FrmDModule.TbEcono.Open;
nAux2 := FrmDModule.TbEconoIMPORTE.value;


lblSaldo.Caption := formatFloat('#,##0.00 €',nAux2);
FINALLY

FrmDmodule.TbEcono.GotoBookmark(dbPos);
FrmDmodule.TbEcono.FreeBookmark(dbpos);
FrmDmodule.TbEcono.EnableControls;
END;



El problema es que al compilar me da fallo, por que me pide unos campos que necesito tener declarados en la tabla, pero que aquí no se como incluir.

¿alguna idea?

Muchas gracias a todos por la ayuda.

Virginia

andres1569 17-10-2003 18:52:55

Hola:

Si te da fallo al compilar, supongo que el error estará en la línea:

nAux2 := FrmDModule.TbEconoIMPORTE.value;

puesto que ese campo TbEconoIMPORTE no lo tienes definido desde Delphi. Para evitarlo, prueba a usar el método, FieldByName de la tabla en cuestión. El compilador no protestará, sólo saltará un error en ejecución si no se halla dicho campo en el Dataset correspondiente:

nAux2 := FrmDModule.TbEcono.FieldByName('IMPORTE').value;

Un saludo

__cadetill 18-10-2003 10:38:20

Cita:

Posteado originalmente por andres1569
puesto que ese campo TbEconoIMPORTE no lo tienes definido desde Delphi
bueno, no estoy totalmente de acuerdo con esto, ya que sí podría (y digo podría) tenerlo definido en Delphi.

Si no es éste el error, sería bueno que Virginia digera en que linea le da el error y cual es el error que le da

Giniromero 22-10-2003 12:45:52

Hola,

Cita:

Si te da fallo al compilar, supongo que el error estará en la línea:

nAux2 := FrmDModule.TbEconoIMPORTE.value;

tenía declarado el campo IMPORTE como campo calculado en la tabla, pero, efectivamente, con esto, que me comentaste,

Cita:

nAux2 := FrmDModule.TbEcono.FieldByName('IMPORTE').value;
no necesito declararlo, cosa que prefiero.

En cuanto al error que me da, es como si en este procedure buscase campos, que tengo declarados en el IDDataSet, que son de la tabla, pero que en este caso no necesito, y no he declarado en el select del SQL.

Por ejemplo. El campo ASIENTO, lo tengo declarado en la tabla econo.

Si le paso a la propiedad SelectSQL con el código,


quote:
--------------------------------------------------------------------------------

TRY
dbPos := FrmDmodule.TbEcono.Getbookmark;
FrmDmodule.TbEcono.Disablecontrols;
FrmDModule.TbEcono.Close;
//borramos el contenido de la propiedad SelectSQL
FrmDModule.TbEcono.SelectSQL.Clear;
//le asignamos el SQL que tenía al inicio la tabla
FrmDModule.TbEcono.SelectSQL.Add('select NUMCLI, SUM(0 - econo.impdebe + econo.imphaber) IMPORTE');
FrmDModule.TbEcono.SelectSQL.Add('from econo');
FrmDModule.TbEcono.SelectSQL.Add('WHERE NUMCLI =:NUMCLI’);
FrmDModule.TbEcono.SelectSQL.Add('GROUP BY NUMCLI’);
FrmDModule.TbEcono.SelectSQL.Add('ORDER BY NUMCLI ');
FrmDModule.TbEcono.Open;
nAux2 := FrmDModule.TbEcono.FieldByName('IMPORTE').value;


lblSaldo.Caption := formatFloat('#,##0.00 €',nAux2);
FINALLY

FrmDmodule.TbEcono.GotoBookmark(dbPos);
FrmDmodule.TbEcono.FreeBookmark(dbpos);
FrmDmodule.TbEcono.EnableControls;
END;


--------------------------------------------------------------------------------
No estoy incluyendo dicho campo en la la consulta SQL, y me resulta el siguiente error:


Cita:

Project xxx raised exception class EDatabaseError with message 'TbEcono: Field 'ASIENTO' not found
He estado viendo posibles formas de añadir, en la consulta sql , estos campos que me va pidiendo, pero si los añado a la consulta, esta queda mucho más complicada, y no me devuelve un registros, como hace esta, sino varios, lo cual no me interesa.

¿Hay alguna manera de que no me los pida?

Tal vez todo esto tenga que ver con que estoy trabajando con un DataModule en el que tengo un IBDataSet, TbEcono, al que le cambio el código del selectSQL, cuando quiero cambiar de consulta , en vez de crearme otro IBDataSet nuevo, para la nueva consulta.

De este IBDataSet tira un DBGrid, (por eso necesito tener declarados los campos), y a la vez pretendo que me haga, de un modo puntual, estas consultas que os he puesto, para que me calcule si el usuario debe dinero o no.

Muchas gracias por todo,

Saludos,

Virginia

__cadetill 22-10-2003 15:29:47

Hola Virginia

Por lo que entiendo de tu explicación, este TIBDataSet tiene campos persistentes declarados, cierto? Si es así, la consulta SQL que lances en él, deberá devolver esos campos, ni más ni menos.

Si no puedes omitir la declaración de los campos persistentes y, sólo necesitas lanzar este tipo de SQL de vez en cuando, te propongo 2 alternativas

1.- Pones un TIBQuery en el DataModule sin campos persistentes y, en él lanzas las consultas SQL (temporales) que necesites en cada momento.

2.- Dependiendo el diseño de la aplicación, la opción 1 no será válida, por lo que, esta segunda opciónsería la que convendría. Ésta es, crear tu misma el componente en ejecución de forma local al procedimiento o función (es la que yo utilizo para evitarme posibles errores)

Código:

procedure ElQueSea;
var
  Q : TIBQuery;
begin
  Q := TIBQuery.Create(Self);
  Q.Database := MyDataBase;
  try
    // lanzo la consulta SQL que necesite
  finally
    FreeAndNil(Q);
  end;
end;

Espero te sirva

Giniromero 22-10-2003 18:05:33

Hola,

Cita:

Por lo que entiendo de tu explicación, este TIBDataSet tiene campos persistentes declarados
Efectivamente, ese es "el mio problema".

He probado el código que me comentas,

code:--------------------------------------------------------------------------------
procedure ElQueSea;
var
Q : TIBQuery;
begin
Q := TIBQuery.Create(Self);
Q.Database := MyDataBase;
try
// lanzo la consulta SQL que necesite
finally
FreeAndNil(Q);
end;
end;
--------------------------------------------------------------------------------

Lo tengo de la siguiente forma en mi procedure,

Cita:


Procedure TFrmFxMain.CalculaSaldo;
var nAux2: integer;
var Q : TIBQuery;
begin

nAux2:=0;
Q := TIBQuery.Create(Self);
Q.Database := FrmDmodule.TbEcono.Database;

TRY

Q.Disablecontrols;
Q.Close;
//borramos el contenido de la propiedad SelectSQL
Q.SQL.Clear;
//le asignamos el SQL que tenía al inicio la tabla
Q.SQL.Add('select NUMALU, SUM(0 - econo.impdebe + econo.imphaber) IMPORTE');
Q.SQL.Add('from econo');
Q.SQL.Add('where NUMALU =:NUMALU ');
Q.SQL.Add('GROUP BY NUMALU ');
Q.SQL.Add('ORDER BY NUMALU ');
Q.Open;
nAux2 := Q.FieldByName('IMPORTE').Value;


lblSaldo1.Caption := formatFloat('#,##0.00 €',nAux2);
FINALLY

Q.EnableControls;
FreeAndNil(Q);
END;
end;

Pero me devuelve el siguiente mensaje de error:

Cita:

Invalid variant type conversion
Por lo que he podido ver, es algo relativo al paso del valor del campo importe, a la variable nAux2, pues si pongo un breakpoint, me da el error tras ejecutar:

nAux2 := Q.FieldByName('IMPORTE').Value;

Si en vez de poner .Value, pongo .asvariant, o .asinteger también me da error.



¿Podría ser que necesita que el campo "IMPORTE" sea un campo persistente?

Gracias por la ayuda.

Virginia

roman 22-10-2003 19:16:41

Cita:

Posteado originalmente por Giniromero
Pero me devuelve el siguiente mensaje de error:

Invalid variant type conversion

Por lo que he podido ver, es algo relativo al paso del valor del campo importe, a la variable nAux2, pues si pongo un breakpoint, me da el error tras ejecutar:

nAux2 := Q.FieldByName('IMPORTE').Value;

Si en vez de poner .Value, pongo .asvariant, o .asinteger también me da error.

¿Podría ser que necesita que el campo "IMPORTE" sea un campo persistente?

No creo que esto tenga que ver con campos persistentes. El error se debe a que no es posible la conversión del dato en la bd a un entero. Posiblemente el campo importe no sea un entero o bien es null en cuyo caso tendrías primero que verificar esto antes de hacer la asignación:

// Saludos

__cadetill 22-10-2003 19:59:11

Algún comentario más (a parte de lo indicado por Román de verificar que no sea null)

A la query le estas pasando una variable. De donde la sacas? no veo que se la asignes!!! :confused:

Por qué haces el DisabledControls si no lo tienes ligado a ningún componente visual?? :p

Eso sí, lo más importante es que verifiques que la consulta devuelva algún valor y que no sea nulo antes de hacer asignaciones

Giniromero 24-10-2003 11:16:47

Hola,


Este es el código con el que consigo que no me de fallos, y me abra la aplicación,

Cita:


PROCEDURE xxxx;
var nAux2: variant;
begin


nAux2:= 0;

Q := TIBQuery.Create(Self);
Q.Database := FrmDmodule.TbEcono.Database;

TRY
Q.Close;
//borramos el contenido de la propiedad SelectSQL
Q.SQL.Clear;
//le asignamos el SQL que tenía al inicio la tabla
Q.SQL.Add('select NUMALU, SUM(0 - econo.impdebe + econo.imphaber) IMPORTE');
Q.SQL.Add('from econo');
Q.SQL.Add('where NUMALU = ' + FrmDModule.TbAlumnosNUMALU.AsString);
Q.SQL.Add('GROUP BY NUMALU ');
Q.SQL.Add('ORDER BY NUMALU ');
Q.Open;
nAux2 := Q.FieldByName('IMPORTE').AsFloat;


lblSaldo1.Caption := formatFloat('#,##0.00 €',nAux2);
FINALLY
FreeAndNil(Q);
END;
lo que pasa, es que, no siempre me muestra, como es de esperar, el saldo real que tiene cada cliente. Creo que, cuando se encuentra campos con valor null, directamente hace mal el calculo, esto es, no considera 0 ese campo null, y no hacer la suma correspondiente. ¿Alguna idea?


Cita:

A la query le estas pasando una variable. De donde la sacas? no veo que se la asignes!!!
eso a sido un despiste del programador ;-)

Cita:

lo más importante es que verifiques que la consulta devuelva algún valor y que no sea nulo antes de hacer asignaciones
y ¿cómo verifico esto?

Gracias por todo, a todos,

Virginia

__cadetill 24-10-2003 14:16:10

Cita:

Posteado originalmente por Giniromero
y ¿cómo verifico esto?
Yo haría algo así
Código:

if not Q.IsEmpty and not Q.FieldByName('Importe').IsNull then
  // hacer asignación o lo que sea
else
  // Query sin valores o campo nulo

El tema de que te devuelva null la suma, acabo de probar en Firebird 1.5 y, aunque un valor de los que entran en la suma sea Null, la suma en sí la hace correctamente devolciendo la suma de los demás registros :(

guillotmarc 24-10-2003 15:21:30

Hola.

Cita:

Posteado originalmente por cadetill
El tema de que te devuelva null la suma, acabo de probar en Firebird 1.5 y, aunque un valor de los que entran en la suma sea Null, la suma en sí la hace correctamente devolciendo la suma de los demás registros :(
Me extraña que la suma te devuelva un valor, en caso de que un registro sea nulo, no deberia hacerlo. Puesto que el estándar SQL indica que un valor operado con nulo, es nulo. Por eso cuando alguno de los valores que interviene en la suma es nulo, el resultado es nulo.

Para solucionarlo, debes utilizar alguna función que te sustituya el nulo por un 0. Por ejemplo, la función COALESCE :

select NUMALU, SUM(0 - COALESCE(econo.impdebe, 0) + COALESCE(econo.imphaber,0)) as IMPORTE
from econo
where NUMALU = :Parametro
GROUP BY NUMALU
ORDER BY NUMALU

El problema es que esto te funcionará en Firebird 1.5, pero creo que Interbase 7 no soporta esta función. En ese caso la tendrás que sustituir por una UDF.

La semana pasada hablamos precisamente de este mismo problema en otro hilo, si lo buscas encontrarás información sobre como utilizar una UDF.

Saludos.

Giniromero 28-10-2003 19:36:19

Gracias por la ayuda,

Voy a ver si con lo que me has ido facilitando soluciono esto.

Saludos

Virginia


La franja horaria es GMT +2. Ahora son las 18:02:14.

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