Hola invitado         02 Sep, 2010 - 04:28
Menú principal
 
Ads
 
Patrocinadores
 
Anuncios
 
© 2009 PortalFox
Cliente-Servidor: Parametrización de Variables. lecturas 5575
 Enviado por Esparta Palma en Lunes, 04 Junio, 2007
Bases de Datos Cuando manejamos la conexión a un DBMS (DataBase Management System) podemos mandar cualquier tipo de datos, no solo caracteres de texto. Aplicable a cualquier servidor de Base de Datos (Microsoft SQL Server, MySQL, PostgreSQL, Firebird, etc).

Esparta Palma Por Esparta Palma, México, D.F.




Es muy común que cuando empezamos a manejar datos de una fuente externa a VFP, es decir, a servidores de base de datos, nos encontremos con la limitación de que únicamente podemos mandar cadenas de texto en las consultas SQL.

Para apoyarnos un poco, tomaremos una típica consulta SQL...

SELECT iID, cClave, cCliente, cRegistro
WHERE (iID > <NumeroInferior > )
AND (iID < < NumeroSuperior > )
FROM Cliente

Donde, obviamente, el "Numero Inferior" y "Numero Superior" serían datos variables a consultar, tomados de algún formulario de VFP.

Nuestro primer intento puede ser intentar formatear la cadena, de manera a que lo que se envía sea igual que la consulta deseada:

lcConsulta = " SELECT iID, cClave, cCliente, cRegistro "+
" WHERE (iID > " + STR(thisform.txtNumerInferior.Value) + ")"+
" AND (iID < " + STR(Thisform.txtNumeroSuperior.Value) + ")"+
" FROM Cliente "

Lo anterior funcionará, ya que igual, tenemos una cadena de texto y los valores, que ya han sido convertidos a cadena serán enviados tal cual a nuestro servidor.

Pero eso, al parecer, no es eficiente... Quizás lo podríamos hacer mejor, no? Pues si, como vimos en un artículo pasado, podríamos usar bloques TEXT ... ENDTEXT, para mejorar nuestra presentación:

WITH ThisForm
lnNumeroInferior = .txtNumeroSuperior.Value
lnNumeroSuperior = .txtNumerSuperior.Value
ENDWITH

TEXT TO lcConsulta NOSHOW TEXTMERGE
SELECT iID, cClave, cCliente, cRegistro
WHERE (iID > <<NumeroInferior>> )
AND (iID < <<NumeroSuperior >> )
FROM Cliente
ENDTEXT

Funciona, si, también hace lo que deseamos, enviará los datos con los valores que queremos sin ningún problema. Pero, hagamos esto un poco más complicado: ¿Qué pasará cuando querramos hacer una búsqueda en base a un dato de tipo caracter? Cambiando un poco el ejemplo, buscaremos el conjunto de datos que cumpla con la condición de encontrar los datos de un cliente con base a la clave (string) del mismo:

SELECT iID, cCliente, cDireccion, dFechaAlta, yAdeudo
FROM Cliente
WHERE cClave = 'ALFKI'


Como vemos en la consulta, y en el caso específico de SQL Server, cuando se hace una query en base a datos de caracteres debemos encerrar dicho valor entre comillas sencillas, ¿sencillo? , ¿o no?

lcCliente = Thisform.txtCliente.Value
TEXT TO lcConsulta NOSHOW TEXTMERGE
SELECT iID, cClave, cCliente, cDireccion
FROM Cliente
WHERE cClave = '<<lcCliente>>'
ENDTEXT

Una vez más, vemos que el ejemplo, también funciona, pero tiene un detalle: debemos formatear cada consulta de acuerdo a los requerimentos de nuestro servidor, y según sea el caso, podría que fuera diferente de un servidor a otro, además de que por lo que a mí respecta, pienso que es bastante engorroso y podría evitarse.

La Parametrización al rescate

La forma sencilla de no tener complicaciones con los distintos tipos de datos de los servidores, y los distintos tipos de datos de VFP, resulta en usar la Parametrización, ¿y que es esto?, consiste en anteponer un símbolo de interrogación justo antes de una variable:

lcCliente = Thisform.txtCliente.Value
TEXT TO lcConsulta NOSHOW
SELECT iID, cClave, cCliente, cDireccion
FROM Cliente
WHERE cClave = ?lcCliente
ENDTEXT
IF SQLExec(lnHandle, lcConsulta, lcCursor) > 0
*** ¿Manipular, mostrar los datos?
*** SELECT (lcCursor)
ELSE
IF AERROR(laError) > 0
Messagebox("Error en la consulta: "+laError[2])
ELSE
Messagebox("Error inesperado en la aplicación")
ENDIF
ENDIF

Como podrás notar, en el bloque TEXT...ENDTEXT hemos prescindido de la función de TEXTMERGE, además de las comillas sencillas, y en su lugar, sólo hemos puesto un símbolo de cierre de interrogación.

¿Qué estamos haciendo?, cuando usamos la Parametrización, delegamos la función de formateo de variables al driver ODBC, VFP se encargará de comunicarle qué tipo de datos es, y casi por arte de magia, hará la conversión pertinente. ¿Sencillo?, asi es, y funcionará con todos los tipo de datos de VFP (no será el caso de objetos, no confundir). Haz el intento ;-).

Nota al margen

En los ejemplos arriba escritos hemos hecho solo consultas de datos, pero aplicará a cualquiera de los comandos de tipo DML (Data Manipulation Language) de SQL, tales como INSERT, UPDATE, DELETE, etc.:

** Insertar datos
TEXT TO lcInsert NOSHOW
INSERT INTO Detalles (cClave, iProductoID, nCantidad, yPrecioVenta, dFechaVenta)
VALUES (?lcClave, ?lnProductoID, ?lnCantidad, ?lyPreciodeVenta, ?ldFechaVenta)
ENDTEXT
IF SQLExec(lnHandle,lcInsert) > 0
*** Datos insertados con éxito
*** Messagebox("Datos insertados con éxito")
ELSE
IF AERROR(laError) > 0
Messagebox("Error al insertar datos:"+laError[2])
ELSE
Messagebox("Error inesperado!!")
ENDIF
ENDIF

** Actualizar un registro
TEXT TO lcUpdate NOSHOW
UPDATE Detalles SET nCantidad = ?lnCantidad
WHERE ( iMovimientoID = ?lnMovimiento )
ENDTEXT
IF SQLExec(lnHandle, lcUpdate) > 0
*** Actualizados con exito
*** Messagebox("Datos actualizados con éxito")
ELSE
IF AERROR(laError) > 0
Messagebox("Error al actualizar el registro:"+laError[2])
ELSE
Messagebox("Error inesperado!!")
ENDIF
ENDIF
** Borrar registro(s)
TEXT TO lcDelete NOSHOW
DELETE FROM Detalles WHERE (iFacturaID = ?lnFactura)
ENDTEXT
llSucess = .F.
IF VERSION(2) >= 9
*** Usar las nuevas características de VFP9 para conocer los registros afectados
llSucess = SQLExec(lnHandle,lcDelete,NULL,aRowsAffected) > 0
IF (llSucess)
lcMessage = "Se han borrado "+STR(aRowsAffected[1,2] ) + ;
" artículos de la Factura "+STR(lnFactura)
ENDIF
ELSE
llSucess = SQLExec(lnHandle,lcDelete) > 0
lcMessage = "Se han borrado todos los articulos de la Factura "+str(lnFactura)
ENDIF
IF llSucess
*** Registros borrados con exito
*** Messagebox(lcMessage)
ELSE
IF AERROR(laError) > 0
Messagebox("Error al intentar borrar los datos:"+laError[2])
ELSE
Messagebox("Error inesperado!!")
ENDIF
ENDIF

Espero que este artículo les sea de utilidad.

Artículos relacionados:

--- Crear Aplicaciones Cliente-Servidor con Visual FoxPro ---
http://www.portalfox.com/article.php?sid=970

--- Introducción a Cliente-Servidor ---
http://www.portalfox.com/index.php?name=Sections&req=viewarticle&artid=25

--- Breve Reseña sobre los conceptos de Cliente-Servidor ---
http://www.portalfox.com/article.php?sid=1000

--- ¿Utilizar Vistas Remotas o SQL Pass Through (SPT) para Cliente-Servidor? ---
http://www.portalfox.com/article.php?sid=996

--- TextMerge y SQL Pass Through (SPT) trabajando juntos ---
http://www.portalfox.com/article.php?sid=680

--- Consultas de mas de 256 cars. a el servidor remoto (SPT y TEXT.. ENDTEXT) ---
http://www.portalfox.com/article.php?sid=1035

--- Cliente-Servidor: Manejo de Fechas ---
http://www.portalfox.com/article.php?sid=2445
--
¸,ø¤º°`°º¤ø,¸¸,ø¤º°`°º¤ø,¸¸,ø¤º°`°º¤ø,¸¸,ø¤º°`°º

Espartaco Palma Martínez
SysOp http://www.PortalFox.com
México D.F.
http://weblogs.foxite.com/esparta/
http://www.espartha.com/blog/
 Versión imprimible  
Cliente-Servidor: Parametrización de Variables. | Entrar/Crear una cuenta | 3 Comentarios
Los comentarios son propiedad de sus respectivos autores.
No somos responsables de su contenido.

Re: Cliente-Servidor: Parametrización de Variables.


por joan_mir (Xjoan_mir@infomail.lacaixa.esX) en 04 Jun, 2007 - 06:24
(Información del usuario  | Enviar un mensaje 
Hola Esparta.

¿Puedes poner un ejemplo de como lo harias con un campo tipo fecha o datetime para hacer una consulta a sql server ?

Un saludo.

Re: Cliente-Servidor: Parametrización de Variables.


por mtovar en 06 Jun, 2007 - 12:33
(Información del usuario  | Enviar un mensaje http://programastop.googlepages.com)
Excelente el tip. Gracias Espartaco. Enorme cantidad de digitación me he evitado.

Solo un comentario. El uso del parámetro no supone que el driver ODBC haga la conversión del tipo de dato. Por ejemplo a mi no me funcionaba un INSERT o UPDATE en el que una variable numérica del formulario iba a actualizar un campo string de la BD. Al momento de definir el parámetro hay que hacer el STR(variable,x,x). Trabajando contra MySQL 5.0 al menos.

Muchas gracias por el aporte y saludos cordiales

Manuel Tovar
Barranquilla - COLOMBIA

Re: Cliente-Servidor: Parametrización de Variables.


por esparta en 10 Jun, 2007 - 10:12
(Información del usuario  | Enviar un mensaje http://www.espartha.com)
MTovar,

>>Por ejemplo a mi no me funcionaba un INSERT o UPDATE en el que una variable numérica del formulario iba a actualizar un campo string de la BD..

Bueno, el driver ODBC tampoco va a adivinar que tipos de datos debe mandar a qué campo, lo que debes de revisar (es decir, le toca al programador) es hacer compatible los tipos de datos mandados, si tu campo es caracter en tu base de datos, entonces tu variable deberá ser de tipo caracter (si fuere numérica), si manejas date/datetime en tu formulario y en tu base de datos en caracter (cosa que he visto que hacen algunos administradores de base de datos) entonces deberás convertirlo a caracter, y así por el estilo. En resumen, solo tienes que mapear las variables a los tipos de datos de tu servidor si y solo si en tu formulario son distintos. Existe una excepción en cuanto a los tipos de datos Date de VFP y los DateTimes de los servidores, lo explico en un artículo posterior al respecto.

Joan Mir, ya tenía programado un artículo al respecto, aquí está el URL:
--- Cliente-Servidor: Manejo de Fechas ---
http://www.portalfox.com/article.php?sid=2245

Gracias por sus comentarios.




Todas las marcas y los logos utilizados en este sitio son propiedad de sus respectivos dueños.
Los artículos, noticias y comentarios son propiedad y responsabilidad de sus respectivos autores.
Copyright © 2000-2010 PortalFox. Todos los derechos reservados.