Primero que nada, debemos tener en cuenta dos puntos importantísimos al respecto.
No existe el tipo de datos Date (Fecha)
En efecto, los DBMS no tienen un tipo de datos Date, en su lugar, se tiene un tipo de datos DateTime (Fecha-Hora), el cuál, al igual que el tipo de dato de DateTime de VFP tiene una precisión de segundos, es decir, un format Dia, Mes, Año, Hora, y Segundos. En VFP las variables DateTime se pueden definir con la función DateTime() o mapearse directamente sobre la asignación de un campo tipo DateTime:
ltFechaInicio = DateTime(lnAnnio, lnMes, lnDia, lnHora, lnSegundos) ltFechaFin = Cursor.tFechaFinLos tipos de datos DateTime, a diferencia de los Date, se basan en segundos, y no en días, por lo que su aritmética varía en consecuencia, nuestro compañero Luis María Guayán ya he escrito un extenso documento sobre esto aquí:
--- Trabajar con fechas y horas en Visual FoxPro ---
http://comunidadvfp.blogspot.com/2014/09/trabajar-con-fechas-y-horas-en-visual.html
Por lo tanto, debemos tener en cuenta este detalle y acostumbrarse a tal hecho, claro está, dependiendo de tu DBMS podrías retornar otro tipo de datos, o en su defecto, sobre el cursor resultante, aplicar la conversión de datos si así fuere necesario.
No existen las fechas vacias
Los DBMS no entienden el concepto de las fechas vacias que maneja VFP, de hecho, dependiendo del manejador de base de datos, obtendrás resultados inesperados, o un error.
Entonces, ¿ Cómo debemos manejar las fechas vacias (ldFecha = {}) ?, las fechas vacias, deberían convertirse todas a valores nulos (ldFecha = .null.), y en las consultas SQL, manejar las funciones pertinentes.
--- ¿Qué es un valor null entre amigos? ---
http://comunidadvfp.blogspot.com/2014/09/que-es-un-valor-null-entre-amigos.html
--- NULL (SQL) ---
http://en.wikipedia.org/wiki/Null_(SQL)
--- Working With Columns That Contain Null Values ---
http://www.databasejournal.com/features/mssql/article.php/3399931
De este modo, si estás contemplando hacer un upsizing desde tablas DBF a un servidor de base datos, entonces, antes deberás cambiarlas a nulos todos aquellos valores que fueran vacios.
UPDATE MiTabla SET dFecha = null WHERE EMPTY(dFecha)
Trabajando con Fechas en los Servidores de Base de Datos
Una vez contemplado la anterior, podemos introducirnos al tema, y como comentaba líneas arriba, no es nada difícil, sólo debemos usar la Parametrización.
En el caso de que manejemos SQL Pass Trough (SPT), sabemos que deberíamos envíar una cadena de texto, es decir, sólo la consulta SQL, y claro, podremos olvidarnos de formatearlo para que concuerde con la manera en que tu servidor maneje los datos.
Durante mucho tiempo se ha debatido en los foros de discusión, que las fechas deberían ser mandadas con formato estándar ANSI: AAAAMMDD.HHSS (20070506.1320), la verdad que eso no es tan cierto, por lo menos en VFP, lo que debemos hacer es hacer uso de la parametrización.
Como muestra, un pequeño código que podríamos utilizar para mandar una consulta a un servidor de Base de Datos SQL Server (cualquier versión):
WITH Thisform
ltFechaInicio = .txtFechaInicio.Value
ltFechaFin = .txtFechaFin.Value
ENDWITH
TEXT TO lcConsulta NOSHOW
SELECT iID, cIDFactura, tFecha, yImporte, nCantidad
FROM DetalleFactura
WHERE Fecha BETWEEN ?ltFechaInicio AND ?ltFechaFin
ENDTEXT
IF SQLExec(lnHandle, lcConsulta, lcCursor) > 0
*** Hacer algo
ELSE
IF AERROR(laError) > 0
Messagebox("Error en la consulta:"+laError[2])
ENDIF
ENDIF
Sencillo? Si, la magia se realiza justo en el driver ODBC, VFP se encarga de comunicarle que es un tipo de datos DateTime y hará la conversión pertinente. Tan fácil como eso.
Retomando el caso de los valores nulos
Como mencionabamos anteriormente, los servidores de Bases de Datos no manejan el concepto de fechas vacias, por lo que a la hora de mandar ese dato, debemos "convertir" las variables a null, y así mandarlas al servidor.
WITH Thisform
iProductoID = .txtProductoID.Value
nCantidad = .txtCantidad.Value
yPrecioVenta = .txtPrecio.Value
IF EMPTY(.txtFecha.value)
tFechaVenta = .null.
ENDIF
ENDWITH
TEXT TO lcSQL NOSHOW
INSERT INTO DetalledeVenta (iProductoID,nCantidad, yPreciodeVenta, tFechaVenta)
VALUES (?iProductoID, ?nCantidad, ?yPrecioVenta, ?tFechaVenta)
ENDTEXT
Notas adicionales
Como nota al margen, debemos también tomar en cuenta que al basarse en tipo de datos DateTime, se debe hacer especial énfasis en que los inicios y fines del día.
Como un ejemplo, supongamos que quisieramos obtener los movimientos realizados únicamente en la fecha 11 de Junio de 2007, entonces, al mandar la consulta:
lcTabla = "DetalledeVenta"
ldFechaInicial = DATE(2007,06,11)
ldFechaFinal = ldFechaInicial+1
TEXT TO lcSQL NOSHOW TEXTMERGE
SELECT idMovimiento, iProductoID, nCantidad, yPrecioVenta
FROM <<lcTabla>>
WHERE tFechaVenta BETWEEN ?ldFechaInicial AND ?ldFechaFinal
ENDTEXT
IF SQLExec(lnHandle,lcSQL,lcCursor) > 0
** Hacer el trabajo con el cursor resultante
SELECT (lcCursor)
***SCAN
***ENDSCAN
ELSE
IF AERROR(laError) > 0
Messagebox("Error en la consulta:"+laError[2])
ELSE
Messagebox("Error inesperado en la aplicacion")
ENDIF
ENDIF
Cuando usamos la parametrización debemos revisar que los tipos de datos de las variables de VFP correspondan a los tipos de datos de la base de datos SQL, es decir, si tu tipo de datos en tu formulario es numérico y en la base de datos es caracter, entonces antes deberías cambiar la variable a enviar a tipo caracter (¿STR(lnNum, 5)?), como caso especial los tipos de datos Date en VFP son compatibles con los tipos DateTime del controlador ODBC, con la única salvedad de que estas fechas serán contemplados con la hora inicial del día.
Espero que les sea de utilidad.
Espartaco Palma Martínez
No hay comentarios. :
Publicar un comentario
Los comentarios son moderados, por lo que pueden demorar varias horas para su publicación.