En el artículo anterior ya hemos visto que para enviarle algún comando al Servidor deberemos usar la función SQLEXEC() del Visual FoxPro.
El segundo parámetro de la función SQLEXEC() es el comando que deseamos enviar. Pero aquí hay varias alternativas, algunas peores y algunas mejores, tal y como veremos a continuación.
Listado 1. Una forma (incorrecta) de enviarle parámetros a la función SQLEXEC()
llComandoOK = SQLEXEC(_Screen.nHandle, "SELECT * FROM BANCOS") = 1
Hay programadores que envían comandos al Servidor de forma similar a la mostrada en el Listado 1. Eso está mal. ¿Por qué?
Porque si la función SQLEXEC() falló y queremos verificar cual fue el problema, deberíamos escribir nuevamente todo lo que está entre comillas, por ejemplo:
Listado 2. Para verificar cual comando se envió al Servidor
llComandoOK = SQLEXEC(_Screen.nHandle, "SELECT * FROM BANCOS") = 1 =MESSAGEBOX("SELECT * FROM BANCOS")
En un comando tan simple y tan sencillo como el mostrado en los listados 1 y 2 no sería problema pero algunos SELECT pueden ser muy largos (como ya has visto en otros artículos de este blog) y por lo tanto escribir nuevamente todo el segundo parámetro sería muy engorroso.
Una mejor alternativa sería escribir:
Listado 3. Guardando el comando en una variable
lcComando = "SELECT * FROM BANCOS" llComandoOK = SQLEXEC(_Screen.nHandle, lcComando) = 1 =MESSAGEBOX(lcComando)
Ahora, el comando que se envía al Servidor previamente se guarda en una variable y es esa variable la que se usa en todos los casos.
Si el comando que deseamos enviar al Servidor es constante, como en los casos hasta aquí mostrados, ya está bien con lo que hicimos, no necesitamos más. Pero en muchos casos necesitamos enviarle al Servidor datos variables y allí ya se complica el asunto.
Listado 4. Enviando un comando con datos variables al Servidor
lnIdenti = 5 lcComando = "SELECT * FROM BANCOS WHERE BAN_IDENTI = " + TRANSFORM(lnIdenti) llComandoOK = SQLEXEC(_Screen.nHandle, lcComando) = 1 =MESSAGEBOX(lcComando)
Al ejecutar el Listado 4. veremos algo similar a:
Captura 1. Viendo el comando que se envió al Servidor
En la Captura 1. vemos el comando que se envió al Servidor, cuando ese comando es muy largo hacerlo de esta forma nos resultará muy útil para buscar y encontrar errores en el texto enviado.
Y hablando de ese tema, cuando el texto a enviar es largo, es preferible utilizar la construcción TEXT…ENDTEXT.
Listado 5. Enviando comandos largos al Servidor
TEXT TO lcComando NOSHOW SELECT * FROM BANCOS WHERE BAN_IDENTI = 5 ENDTEXT llComandoOK = SQLEXEC(_Screen.nHandle, lcComando) = 1 =MESSAGEBOX(lcComando)
Escribir lcComando = «algún texto aquí» tiene la desventaja de que ese texto no puede superar los 254 caracteres, en cambio si se usa la construcción TEXT…ENDTEXT se puede sobrepasar ese límite, sin ningún problema. Por lo tanto, es mejor acostumbrarse a usar siempre TEXT…ENDTEXT y así el texto siempre será aceptado, sin importar cuantos caracteres escribamos.
¿Y cómo haríamos para enviarle datos variables al Servidor?
Listado 6. Una forma para enviarle datos variables al Servidor
M.IDENTI = 5 TEXT TO lcComando NOSHOW SELECT * FROM BANCOS WHERE BAN_IDENTI = ?M.IDENTI ENDTEXT llComandoOK = SQLExec(_Screen.nHandle, lcComando) = 1 =MessageBox(lcComando)
Fíjate que dentro de la construcción TEXT…ENDTEXT usamos un símbolo de pregunta antes del nombre de la variable. Para que esto funcione, esa variable debe ser PRIVATE o debe ser PUBLIC. Como seguramente ya sabes, no se recomienda usar PUBLIC, por lo tanto lo mejor sería que usaras PRIVATE.
Al ejecutar el Listado 6. veremos algo similar a esto:
Captura 2. El comando que se envió al Servidor usando una variable
¿Cuál es el problema con esta forma de enviar comandos al Servidor? Que no se ve cual es el valor que se envió. En este caso vemos ?M.IDENTI pero no sabemos cual es el valor que está guardado en M.IDENTI
Listado 7. Viendo los valores de las variables enviadas al Servidor
M.IDENTI = 5 TEXT TO lcComando TEXTMERGE NOSHOW SELECT * FROM BANCOS WHERE BAN_IDENTI = <<M.IDENTI>> ENDTEXT llComandoOK = SQLExec(_Screen.nHandle, lcComando) = 1 =MessageBox(lcComando)
Al ejecutar el Listado 7. lo que veremos será:
Captura 3. Viendo las variables enviadas al Servidor
Fíjate que en el Listado 7. después del TEXT TO se escribió TEXTMERGE. ¿Por qué? Porque esa palabra TEXTMERGE es la que le indica al Visual FoxPro que debe evaluar el contenido de la variable. Pero además, se usaron los símbolos << y >> para indicarle cual es la variable.
Desde luego que podríamos tener muchas variables, por ejemplo:
Listado 8. Enviando varias variables al Servidor
M.TABLA = "BANCOS" M.COLUMNA = "BAN_NOMBRE" M.IDENTI = 5 TEXT TO lcComando TEXTMERGE NOSHOW SELECT <<M.COLUMNA>> FROM <<M.TABLA>> WHERE BAN_IDENTI = <<M.IDENTI>> ENDTEXT llComandoOK = SQLExec(_Screen.nHandle, lcComando) = 1 =MessageBox(lcComando)
Al ejecutar el Listado 8. lo que veríamos sería:
Captura 4. Enviando varias variables al Servidor y viendo sus contenidos
Y si preferimos que el SELECT no esté en varias líneas sino todo seguido, podríamos escribir:
Listado 9. Para que las cláusulas del SELECT se muestren una a continuación de la otra
M.TABLA = "BANCOS" M.COLUMNA = "BAN_NOMBRE" M.IDENTI = 5 TEXT TO lcComando TEXTMERGE NOSHOW PRETEXT 15 SELECT <<M.COLUMNA>> FROM <<M.TABLA>> WHERE BAN_IDENTI = <<M.IDENTI>> ENDTEXT llComandoOK = SQLExec(_Screen.nHandle, lcComando) = 1 =MessageBox(lcComando)
Al ejecutar el Listado 9. lo que veremos sería:
Captura 5. Las cláusulas del SELECT una a continuación de la otra
Para que se muestre en una sola línea en la construcción TEXT…ENDTEXT se escribió PRETEXT 15.
El autor de este blog prefiere ver los comandos como se muestra en la Captura 4. pero hay gente que prefiere verlos como se muestra en la Captura 5. así que para satisfacer ambos gustos se mostraron las dos formas.
Conclusión:
La función SQLEXEC() nos permite enviar solicitudes al Servidor y nos devuelve el resultado de la solicitud. Tenemos varias maneras de enviar esas solicitudes, tal y como pudimos ver en este artículo.
Menos de la manera mostrada en el Listado 1., la cual jamás deberíamos usar, dependiendo de las circunstancias podríamos usar alguna de las otras alternativas.
Artículos relacionados:
De DBF a SQL (1). Introducción
De DBF a SQL (2). Reemplazando comandos
De DBF a SQL (3). Entendiendo a los cursores
De DBF a SQL (4). Ejemplos de usar SELECT con una sola tabla
De DBF a SQL (5). Las funciones agrupadas
De DBF a SQL (6). Agrupando filas
De DBF a SQL (7). Poniéndoles condiciones a los grupos
De DBF a SQL (8). Ordenando las filas
De DBF a SQL (9). Uniendo tablas
De DBF a SQL (10). Obteniendo las primeras filas de una tabla
De DBF a SQL (11). Relacionando una tabla con otra tabla
De DBF a SQL (12). Relacionando una tabla consigo misma
De DBF a SQL (13). Relacionando a varias tablas entre sí
De DBF a SQL (14). Más sobre el uso de DISTINCT
De DBF a SQL (15). Usando subconsultas
De DBF a SQL (16). Más sobre las subconsultas
De DBF a SQL (17). Ejemplos de subconsultas
De DBF a SQL (19). Hallando los porcentajes sobre un total
De DBF a SQL (20). Los operadores especiales de comparación
De DBF a SQL (21). La técnica de los dos cursores
De DBF a SQL (22). Optimizando el uso del operador de comparación especial IN
De DBF a SQL (23). Usando la función CAST()
De DBF a SQL (24). Buscando texto
De DBF a SQL (25). Creando tablas y cursores
De DBF a SQL (26). INSERT, UPDATE, y DELETE, con subconsultas
De DBF a SQL (27). Entendiendo Cliente/Servidor
De DBF a SQL (28). Conectándose a un Servidor
De DBF a SQL (29). Las cadenas de conexión ODBC a los motores SQL más populares
De DBF a SQL (30). Conectándose mediante ADO a las bases de datos
De DBF a SQL (31). Optimizando la escritura de los SELECT
De DBF a SQL (32). Mejorando la estética de los SELECT
De DBF a SQL (33). Usando la función SQLEXEC()
El índice del blog VFPavanzado