Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Firebird e Interbase (https://www.clubdelphi.com/foros/forumdisplay.php?f=19)
-   -   Paso algo rarísimo con una Fecha y un Stored Procedure (https://www.clubdelphi.com/foros/showthread.php?t=74279)

gluglu 09-06-2011 11:10:52

Paso algo rarísimo con una Fecha y un Stored Procedure
 
Hola a tod@s !

Esto sí que no lo entiendo .... :confused: :confused:

En Firebird 2.1, creo un Stored Procedure (con IBExpert) de la siguiente manera :

Código SQL [-]
CREATE OR ALTER PROCEDURE SP_PRUEBA 
returns (
    avw_date date)
as
begin
  AVW_DATE = Date 'TODAY';
  suspend;
end

Tan simple como esto, que es asignar la fecha de hoy (del sistema) a una variable de output.

Voy haciendo pruebas cambiando la fecha del sistema (Win XP).

Pues bien .... siempre me devuelve la misma fecha (!!) hasta que vuelva a recompilar con el IBExpert ese SP. Es decir, recompilo, y ahora la fecha está en 09 Jun, y me devuelve correctamente 9 Jun. Cambio la fecha del sistema a 10 Jun, a 11 Jun, etc, y siempre me sigue devolviendo 9 Jun. Dejo la fecha a 11 Jun, recompilo y me devuelve 11 Jun. Y así siempre lo mismo hasta que no vuelvo a recompilar !

:eek: :eek:

... no lo entiendo !!

Ayuda please ! :o

gluglu 09-06-2011 12:06:53

Lo he podido resolver utilizando 'Current_Date' en vez de 'Today'.

Pero aun así, no entiendo el por qué. Utilizo 'Today' de manera habitual en muchos otros Stored Procedure's y nunca me había dado un problema. Me encontraba creando un procedimiento nuevo, desde hace dos días, y me daban resultados incongruentes, hasta llegar a encontrar el motivo que era la compilación.

Simplificando al máximo ese nuevo SP, llegué al SP que indiqué arriba, y no puedo aún comprender por qué Firebird devuelve ese resultado incomprensible.

Casimiro Notevi 09-06-2011 12:22:12

Yo uso current_date, pero en tu caso no sé para qué sirve poner date delante de 'today', ¿qué ocurre si lo quitas?, ¿para qué sirve?

Código SQL [-]
CREATE OR ALTER PROCEDURE SP_PRUEBA 
returns (
    avw_date date)
as
begin
  AVW_DATE = 'TODAY';
  suspend;
end
Lo he probado y al principio me salia como comentas, 9 de junio, cambié la fecha a 10 de junio, lo vuelvo a ejecutar y... 9 de junio, miré la fecha y estaba en 9 de junio, vaya, es que no la he cambiado, la pongo en 10 de junio, le doy a "aplicar", lo pruebo y... 9 de junio. No puede ser, miro la fecha y tiene 9 de junio. Vale, ya sé por qué me pasa a mí, es que yo uso virtualbox sobre linux y tengo configurado que el sistema huesped coja la fecha del sistema anfitrión. ¿No será ese tu caso?

También sería lo mismo si tienes un servidor donde está la BD, es en él donde debes cambiar la fecha, evidentemente.

gluglu 09-06-2011 12:44:03

Hola Casimiro ....

Ya he hecho más pruebas y ya tengo explicación ! :rolleyes:

Respecto de la fecha del servidor, indiqué que utilizo Win XP, y cambiando la fecha del sistema, me cambio 100% la fecha del servidor Firebird que está en la misma máquina, porque cualquier select que hago con el IBExpert me devuelve la fecha correcta.

Bueno, explico ya lo que yo creo que pasa ....

Utilizo el 'Date' delante porque en muchas partes del SP completo (que no lo puse porque son unos cientos de líneas), hago muchas operaciones de fechas, y en la mayoría de los casos, si no utilizo el 'Date' para convertir el String 'TODAY' en una fecha, el compilador me lanza un error.

Al simplificar a una única línea mi SP, llegué al que indiqué arriba, y las pruebas de hecho las estaba realizando con Date 'TODAY'.

Al parecer, de esta manera lo que hace el compilador del SP, es convertir en el momento de compilar la variable 'TODAY' del sistema (es decir, la fecha actual), en un 'Date' y directamente lo graba en la propia BBDD. Lo que provoca, al parecer, que cada vez que se compila, el SP cambia y graba la fecha del momento en que se compila, hasta la próxima compilación, que es lo que me ocurría.

Este problema se soluciona, o bien utilizando Current_Date, o bien, como tu dice, quitando el Date de delante, con lo que al ser una variable de Output definida como tipo fecha, no dá error al compilar. Y lo he comprobado, y sin 'Date' delante funciona correctamente. Claro, ya no convierte el compilador un valor concreto al compilar, sino que funciona como debe de funcionar, y cada vez que se ejecuta el SP, devuelve la fecha correcta del sistema.

Pero mi problema en el SP general era que tenía que hacer un Select con una operación de fechas que implicaba el 'Today'.

Código SQL [-]
For Select distinct case when AW.TYPE_Q_RELEASE = 1
                         then Current_Date + AW.Q_RELEASE
                         else Current_Date + (AW.Q_RELEASE * 7)
                    end
    from AVAIL_WARNINGS AW
    where AW.DATETO >= 'TODAY'
    and AW.Q_RELEASE  is not null
    and AW.CATEGORYNO = :AVW_CATEGORYNO
    into AVW_DATE
do begin
  ...

En este caso, si en vez de Current_Date, como ahora finalmente ha quedado, utilizaba 'TODAY', el compilador lo tomaba como String y me lanzaba un error. Por eso, como en otras muchas partes, decidí poner Date 'Today' (donde ahora pone Current_Date) para que el Select funcionara. Y el compilador no daba error y todo perfecto.

Pero al funcionar normalmente con datos, los resultados eran incongruentes. Debo de concluir que de nuevo el compilar cogía, y grababa directamente en el SP el 'Date 'Today'' como un valor concreto, cogiendo la fecha del sistema en el momento de la compilación.

Concluyo que, de acuerdo con la documentación de Firebird, si el 'TODAY' va en los campos que debe de devolver un Select, se ha de utilizar Current_Date, y en cualquier otra parte del SP, o del propio Select (por ejemplo en el Where), se puede utilizar igualmente 'TODAY', que en ese caso para que no se interprete como un String, deberá llevar delante el 'Date'.

Pero claro, esto sólo ocurre en los SP, que deben de ser compilados y grabados en la BBDD. Porque en cualquier sentencia normal SQL,
Código SQL [-]
Select Date 'TODAY' from ...
funciona perfecta y correctamente.

De hecho, en el Select normal (que no va dentro de un SP), si se utiliza sólo 'TODAY', te devuelve un String, y para que te devuelva la fecha correcta, o bien pones 'Date' delante, o hace un Cast a tipo fecha,
Código SQL [-]
Select Cast('Today' as Date) from ...

.... lo que pasa que me ha llevado casi 6 - 7 horas encontrar esta explicación y poder explicar los resultados incongruentes que me devolvía el SP.

Espero que pueda servir a cualquier otra persona que en algún momento se encuentre con un problema parecido ! ;)

Saludos y gracias !

Casimiro Notevi 09-06-2011 13:50:46

Si es que todo tiene explicación, lo difícil es averiguarla :)

fjcg02 09-06-2011 14:03:38

Para vuestra información, yo he usado current_date y 'NOW'.

'NOW' se comporta de diferente manera, ya que en un insert me pone la fecha actual - si lo utilizo para actualizar un campo timestamp o date - , y en una select me devuelve un string 'NOW', Para que ponga la fecha en la select hay que hacer el cast CAST('NOW' as date).

Saludos

Delphius 09-06-2011 19:25:24

Que yo sepa en los libros de Firebird cuando habla del tema de las constantes predefinidas como literales como NOW, TODAY, TOMORROW y YESTERDAY, SIEMPRE debe utilizarse CAST(xxx AS yyy) para hacer las debidas conversiones y asegurar de que el tipo sea correctamente interpretado.

Asi que no veo el porqué de extrañarse esto. ;)

Saludos,

gluglu 10-06-2011 10:40:22

Estoy totalmente de acuerdo con Delphius en el caso de que estemos hablando de una sentencia Select.

Pero mi problema, aunque se manifestara en el Select (por no utilizarlo correctamente), venía de que en otras partes de un SP, que no son Select's, tengo que utilizar el literal 'TODAY', por ejemplo :

Código SQL [-]
if (:SEL_TYPE_Q_RELEASE = 1) then begin
  if ((:SEL_DATEFROM > Date 'Today') and
      (not (Date 'Today' + :SEL_Q_RELEASE > :SEL_DATEFROM))) then begin
    AUX_DATE = :SEL_DATEFROM;
  end
  else begin
    AUX_DATE = Date 'Today' + :SEL_Q_RELEASE;
  end
end

Aquí es obligatorio utlizar el 'Date' antes del 'Today', porque si no, como ya dije en los anteriores hilos, el compilador del Procedimiento Almacenado me lanza un error.

Tampoco hay problema de utilizar el 'Today' directamente en la parte condicional de un Select, tal y como también mostré en un ejemplo más arriba. Como el compilador sabe ya que la variable que afecta al 'Today' es del tipo fecha, pues no lanza error.

Era por ello que, por inercia, utilicé el 'Date Today' también en la parte de los campos del Select, y es ahí donde me dieron los problemas, y como bien dice Delphius, si hubiera utilizado directamente el Cast, tal y como especifican los manuales, no hubiera tenido esos quebraderos de cabeza.

:o


La franja horaria es GMT +2. Ahora son las 18:45:44.

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