PDA

Ver la Versión Completa : Sobre el uso de ParamByName


salvica
24-11-2008, 15:42:11
Hola a tod@s.

El otro día digamos que "me llamaron la atención" (en plan coloquial) sobre la forma que tenía de comparar fechas encerrádolas entre comillas y que era mejor utilizar ParamByName en su lugar.

Bien, hasta ahora el método de encerrar la fecha entre comillas nunca me habia dado problemas (Delphi-7, Zeos-6 y MySql-5) y pensaba que era lo correcto (mejor con un ejemplo)

Sacar los datos entre las 21:00:00 de ayer y las 00:00:00 horas de mañana para las horas "en punto"

Mi forma ;) devuelve 26 filas

SQL.Add( ' WHERE (fecha="2008-11-23" AND DATE_FORMAT(hora, "%H:%i:%s")="21:00:00")' );
SQL.Add( ' OR (fecha="2008-11-24" AND DATE_FORMAT(hora, "%i:%s")="00:00")' );
SQL.Add( ' OR (fecha="2008-11-25" AND DATE_FORMAT(hora, "%H:%i:%s")="00:00:00")' );


Con ParamByName devuelve una sola fila

SQL.Add( ' WHERE (fecha = :FechaAyer AND DATE_FORMAT(hora, "%H:%i:%s")="21:00:00")' );
SQL.Add( ' OR (fecha = :FechaHoy AND DATE_FORMAT(hora, "%%i:%s")="00:00")' );
SQL.Add( ' OR (fecha = :FechaMana AND DATE_FORMAT(hora, "%H:%i:%s")="00:00:00")' );
SQL.Add( ' ORDER BY psensor.clave' );
ParamByName('FechaAyer').AsDate := MI_FECHA-1;
ParamByName('FechaHoy').AsDate := MI_FECHA;
ParamByName('FechaMana').AsDate := MI_FECHA+1;


¿No se utiliza asi?

Gracias anticipadas
Salvica

pborges36
24-11-2008, 15:52:44
Hola Particularmente yo usaria esto:


SQL.Add( ' WHERE (fecha = :FechaAyer AND DATE_FORMAT(hora, "%H:%i:%s")="21:00:00")' );
SQL.Add( ' OR (fecha = :FechaHoy AND DATE_FORMAT(hora, "%%i:%s")="00:00")' );
SQL.Add( ' OR (fecha = :FechaMana AND DATE_FORMAT(hora, "%H:%i:%s")="00:00:00")' );
SQL.Add( ' ORDER BY psensor.clave' );
ParamByName('FechaAyer').AsString := FormatDatetime('yyyy-mm-dd',MI_FECHA-1);
ParamByName('FechaHoy').AsString := FormatDatetime('yyyy-mm-dd',MI_FECHA);
ParamByName('FechaMana').AsString := FormatDatetime('yyyy-mm-dd',MI_FECHA+1);


y nunca me dio problemas.
Saludos.

salvica
24-11-2008, 16:08:56
Hola Particularmente yo usaria esto:

Código Delphi [-] (http://www.clubdelphi.com/foros/#)SQL.Add( ' WHERE (fecha = :FechaAyer AND DATE_FORMAT(hora, "%H:%i:%s")="21:00:00")' ); SQL.Add( ' OR (fecha = :FechaHoy AND DATE_FORMAT(hora, "%%i:%s")="00:00")' ); SQL.Add( ' OR (fecha = :FechaMana AND DATE_FORMAT(hora, "%H:%i:%s")="00:00:00")' ); SQL.Add( ' ORDER BY psensor.clave' ); ParamByName('FechaAyer').AsString := FormatDatetime('yyyy-mm-dd',MI_FECHA-1); ParamByName('FechaHoy').AsString := FormatDatetime('yyyy-mm-dd',MI_FECHA); ParamByName('FechaMana').AsString := FormatDatetime('yyyy-mm-dd',MI_FECHA+1);


y nunca me dio problemas.
Saludos.
Hola pborges36, gracias por responder tan rápido

No me vale, me sigue dando una fila. Supongo que tambien debería formatear la condición, no? (lo acabo de probar y tambien saca una sola fila)

Gracias
Salvica

ContraVeneno
24-11-2008, 16:26:38
¿y si utilizas "between" no funciona?


with unQuery do begin
..
SQL.Add('Where Fecha between :FechaAyer and :FechaManana');
...
ParamByName('FechaManana').AsDateTime := MI_FECHA+1;
ParamByName('FechaAyer').AsDateTime := MI_FECHA-1;
...

Lepe
24-11-2008, 16:41:27
Yo pasaría las horas por parámetros también (es más elefante).

Siempre que deciis que no os da problema usais un formato de fecha americano, y ese es el que toma por defecto los motores (pero podría cambiar).

Al usar parámetros nos quitamos de problemas.

Otro posible problema, es que AsDate también puede estar pasando la hora (ya que Tdate y Tdatetime viene a ser lo mismo), aconsejo usar:

ParamByName('FechaAyer').AsDate := trunc(MI_FECHA-1);
ParamByName('FechaHoy').AsDate := trunc(MI_FECHA);
ParamByName('FechaMana').AsDate := trunc(MI_FECHA+1);
como sabemos, un Datetime es un Extended que guarda la hora en la parte fracionaria, quitándola, nos aseguramos de no pasarle hora ninguna en ese parámetro.

Saludos

salvica
24-11-2008, 16:53:37
¿y si utilizas "between" no funciona?

Código Delphi [-] (http://www.clubdelphi.com/foros/#)with unQuery do begin .. SQL.Add('Where Fecha between :FechaAyer and :FechaManana'); ... ParamByName('FechaManana').AsDateTime := MI_FECHA+1; ParamByName('FechaAyer').AsDateTime := MI_FECHA-1; ...


Hola ContraVeneno, el problema no es la fecha, sino que debe recoger solo desde las 21:00:00 de ayer hasta las 00:00:00 de mañana (era parte de la condición del ejemplo) :D

Saludos
salvica

ContraVeneno
24-11-2008, 17:07:00
Hola ContraVeneno, el problema no es la fecha, sino que debe recoger solo desde las 21:00:00 de ayer hasta las 00:00:00 de mañana (era parte de la condición del ejemplo) :D

Saludos
salvica

ya, vaya:


Var FechaAyer, FechaManana: TDateTime;
...
FechaAyer := EncodeDateTime(YearOf(Fecha-1), MonthOf(Fecha-1), DayOf(Fecha-1), 21, 00, 00);
...
SQL.Add('Where Fecha between :FechaAyer and :FechaManana');
ParamByName('FechaAyer').AsDateTime := FechaAyer
...

Lepe
24-11-2008, 17:19:16
...pero en la hora 0:00:00 ya ha cambiado la fecha, es una lata andar con fecha de hoy, de mañana, etc...

No te vale algo así: fecha = :fecha and (hora between :hora1 and hora2)
En hora1 le pasas 21:00 (formato time), y en hora2 le pasas 23:59:59.999

Así usas un parámetro de fechas menos.:confused:


Saludos

salvica
24-11-2008, 17:50:24
Perdonar la tardanza, estaba probando lo anterior :)

SQL.Add( ' WHERE fecha BETWEEN :FechaAyer AND :FechaManana' );
SQL.Add( ' AND DATE_FORMAT(hora, "%i:%s")="00:00"' );
SQL.Add( ' ORDER BY clave' );
ParamByName('FechaAyer').AsDateTime := EncodeDateTime(YearOf(FECHA-1), MonthOf(FECHA-1), DayOf(FECHA-1), 23, 0, 0, 0);
ParamByName('FechaManana').AsDateTime := EncodeDateTime(YearOf(FECHA+1), MonthOf(FECHA+1), DayOf(FECHA+1), 0, 0, 0, 0);

No funciona :mad:, me coge los tres días enteros

ContraVeneno
24-11-2008, 18:06:07
mmmkelas, pues entonces no entendí lo que estas buscando... déjame darle otra leída.

salvica
24-11-2008, 18:23:25
Mira contraveneno, tengo unas tablas que contienen datos recogidos de unos sensores, por lo que vienen en formato Fecha, Hora, Valor y Calidad, por eso lo de consultar en unas horas determinadas. Parece ser que con el ParamByName se resuelve (o lo he reuelto) así:

SQL.Add( ' WHERE ( (fecha = :FechaAyer AND HOUR(hora)=21)' );
SQL.Add( ' OR (fecha = :FechaHoy)' );
SQL.Add( ' OR (fecha = :FechaManana AND HOUR(hora)= 0)' );
SQL.Add( ' ) AND DATE_FORMAT(hora, "%i:%s")="00:00"' );
SQL.Add( ' ORDER BY clave' );
ParamByName('FechaAyer').AsDateTime := Trunc(FECHA_PRESION-1);
ParamByName('FechaHoy').AsDateTime := Trunc(FECHA_PRESION);
ParamByName('FechaManana').AsDateTime := Trunc(FECHA_PRESION+1);

La parte DATE_FORMAT(hora, "%i:%s")="00:00"' ) es la que me deja cojer los valores de las "horas en punto"

Gracias a todos
Salvica

Lepe
24-11-2008, 18:28:50
Editaaaaaado otra vez:

Pues entre tu última repuesta y esto, creo que vamos volando ;)

Sí que hay que darle vueltas al tema jeje.

SQL.Add( ' WHERE ( ');
SQL.Add( ' ((fecha between :FechaAyer and :FechaAyer + 1) AND (Hour(hora) between 21 and 23))' ); //ayer y hoy entre las 21 y 23
SQL.Add( ' OR ((fecha between :FechaAyer +1 and FechaAyer +2) AND (HOUR(hora)= 0))' ); // hoy y mañana a las 0:00
SQL.Add( ' )');
SQL.Add( ' AND (DATE_FORMAT(hora, "%i:%s")="00:00")');
SQL.Add( ' ORDER BY psensor.clave' );
ParamByName('FechaAyer').AsDate := trunc(MI_FECHA);


Saludos