domingo, 11 de diciembre de 2011

SQL y Visual Basic para Access

Lo más común es usar Visual Basic para hacer macros en Excel, sin embargo también existen la posibilidad de usar Visual Basic en los otros productos de la suite Office. A continuación veremos algunos métodos y su uso para Access y en particular en el uso de SQL.

SQL es un lenguaje ampliamente utilizado para hacer consultas en bases de datos, gestores populares de base de datos como MySQL, postgreSQL (web), Oracle, entre otros lo utilizan. Cuando hacemos consultas en Access es SQL el lenguaje que el programa ocupa para hacerlas aunque nos muestra la interfaz de diseño de consultas. Los que lo desconozcan pueden encontrar un tutorial en w3schools.

Todo el resto después del salto.

Consultas como strings (cadenas)
Lo primero que debemos saber es que las frases en SQL son tratadas como strings, por lo que pueden ser contenidas en variables, ser concatenadas, entre otros. Por ejemplo podemos tener algo así:
SelectSQL = "SELECT NombreCliente FROM Cliente"

Donde SelectSQL es una variable del tipo string que contiene la consulta que mostrará el atributo NombreCliente de todos los datos de la tabla Cliente. Esta consulta aun no ha sido ejecutada, solo tenemos el código que la contiene.

Consultas tipo SELECT
La particularidad de este tipo de consultas es que entregan como resultado una "tabla", para Visual Basic esto es un record set, es decir un conjunto de registros, cada registro es el equivalente a una fila en Access por lo que tiene la información para todos los atributos de solo uno de los objetos consultados.

Para ejecutar una consulta del tipo SELECT y obtener su record set se utiliza el método Database.OpenRecordset. Por ejemplo con la siguiente línea de código guardaré en una variable llamada SelectSQLResultado el resultado de la consulta.

Set SelectSQLResultado = CurrentDb().OpenRecordset(SelectSQL)

También se pudo haber hecho sin guardar anteriormente la consulta en un string, así:

Set SelectSQLResultado = CurrentDb().OpenRecordset("SELECT NombreCliente FROM Cliente")

Las variables del tipo recordset (como la que acabamos de crear: SelectSQLResultado) capturan la información de toda la consulta.
Sin embargo, cuando se les pide información solo la entregan sobre el registro en el que se encuentran operando el que por defecto es el primero. En este caso si le pedimos al recordset la información sobre NombreCliente el resultado será "Sebastián" y no todo el conjunto de nombres. Para pedir información al recordset debemos hacerlo así: NombreRecordSet(""). Por ejemplo en este caso sería:

SelectSQLResultado("NombreCliente")

Si queremos pasar al siguiente registro se debe usar el método MoveNext sobre nuestro recordset. En nuestro caso sería:

SelectSQLResultado.MoveNext

Si después de aplicar esto volvemos a ejecutar SelectSQLResultado("NombreCliente") este ya no nos arrojará "Sebastián" como resultado, si no "Giovanni" pues el programa entiende que hemos avanzado en el orden de registros.

Una propiedad interesante de los recordset y que es muy usada es saber cuando termina el conjunto de registros. Esto es capturado en la propiedad "End of File" o EOF. En nuestro ejemplo sería:

SelectSQLResultado.EOF

Finalmente, cuando se dejan de ocupar los registros se debe cerrar el recordset para que esta variable no ocupe memoria ni interfiera en el resto del código. Esto se hace usando el método Close() sobre el recordset. En nuestro caso sería:

SelectSQLResultado.Close()

Una estructura que yo usaba mucho cuando trabajaba con este tipo de cdigo era aplicar algo al código o usar las variables con ayuda de un ciclo, lo que quedaría algo así:

Set SelectSQLResultado = CurrentDb.OpenRecordset("SelectSQL") 'aquí se establece cual es el nombre del recordset
Do While SelectSQLResultado.EOF
'<- esto detiene el codigo cuando se han terminado de recorrer los registros '
'")
SelectSQLResultado.MoveNext

Loop
SelectSQLResultado.Close()


Consultas tipo INSERT, DELETE y UPDATE
Este tipo de consultas tienen la particularidad de no devolver una tabla, si no que tienen un impacto directo sobre la base de Enlacedatos ya sea insertando, borrando, o actualizando registros. Por lo que el resultado de estas consultas no debe ser guardado en un recordset.

En nuestro ejemplo usaremos una consulta del tipo INSERT que colocará un nuevo registro en nuestra base de datos con un cliente llamado Pablo.

InsertSQL = "INSERT INTO Clientes (NombreCliente) VALUES ('Pablo')"

Ahora hay que ejecutar nuestra consulta, por lo que ocuparemos el método Database.Execute del siguiente modo:

CurrentDb().Execute InsertSQL, dbFailOnError

Esta linea de código ha ejecutado la consulta InsertSQL con la opción Fail on Error. Esta opción es la más usada y permite que el código no tenga efecto si es que hubiese un error en su ejecución. Mi recomendación es que siempre utilicen esta opción o al menos mientras están creando el código pues recuerden que los cambios en la base de datos no se pueden deshacer (fácilmente) y en ocasiones son costosos. Pueden ver las otras opciones disponibles para este método en este enlace.

Es usual utilizar ambos tipos de código en el mismo problema, por ejemplo en el caso de que a partir de una consulta se necesite insertar en diversas tablas la información obtenida de la consulta.

- Sebastián Cisterna (@scisterna)

No hay comentarios:

Publicar un comentario