En este artículo les mostrare como hacer algunas de las tareas mas típicas a la hora de trabajar con bases de datos. Veremos como realizar altas, bajas y modificaciones de datos, realizar consultas y hacer uso de transacciones.
Una de las formas mas simple para trabajar con una base de datos desde Python, es hacer uso de DB-API. DB-API es una especificación estándar de accedo a base de datos, que se compone de dos niveles: un primer nivel que funciona como una interface genérica para acceder a cualquier base de datos, y un segundo nivel compuesto por los drivers propios de cada motor de base de datos. Este esquema, nos permite lograr mayor independencia con respecto al motor de base de datos que usemos, y nos simplifica enormemente tareas como el cambio de una base de datos por otra.
Para los ejemplos usaré MySQL como motor de base de datos. Teniendo en cuenta lo dicho en el párrafo anterior, antes de empezar a trabajar, debemos instalar el driver que realmente se encargara de los detalles del acceso a MySQL. Para instalar el driver (al menos Linux) puedes hacer uso de los repositorios, ya que en las distribuciones mas populares lo podemos encontrar por defecto. El nombre del driver es MySQLdb. En el caso de Ubuntu (como es mi caso), el paquete que debemos instalar es: Python-MySQLdb.
Asumiendo que tienes instalado Python y MySQL; al instalar el driver MySQLdb, ya estamos listos para empezar a trabajar.
Trabajando con MySQLdb
Importar MySQLdb
Antes de poder conectarnos a una base de datos MySQL e interactuar con esta, debemos importar el módulo MySQLdb desde nuestro script Python:import MySQLdb
Conectarse a la base de datos
Una vez importado el modulo MySQLdb, nos conectamos del siguiente modo:cnn = MySQLdb.connect(host='localhost', user='usuario_mysql',passwd='password', db='base_de_datos')
Como puedes ver, para conectarnos a MySQL, usamos el método Connect() de MySQLdb, al cual le pasamos como parámetro, la dirección del servidor, el usuario, la contraseña y la base de datos. Debes tener en cuenta que esto es valido para conectarnos a MySQL, pero los parámetros de conexión difieren entre los distintos gestores de bases de datos.
Crear un cursor
Luego de conectarnos, debemos crear un cursor para poder realizar las acciones que necesitemos sobre la base de datos; para crearlo escribimos lo siguiente:mi_cursor = cnn.cursor()
El cursor lo creamos haciendo uso del método cursor() del objeto que representa la conexión, en el ejemplo, el objeto se llama cnn, y fue instanciado como resultado de la ejecución de MySQLdb.connect() cuando nos conectamos a la base de datos.
Agregar un registro
Con el cursor creado, ya podemos interactuar con la base de datos. Para agregar un registro a la base de datos, utilizaremos el método excecute() del cursor. En realidad, este método no solo permite agregar registros, sino que lo que hace es enviar a la base de datos, el código SQL que especifiquemos como parámetro. Suponiendo que en nuestra base de datos tenemos una tabla llamada “tblArticulos” con 2 campos (“ID” y “Descripcion”), para agregar un nuevo registro escribiríamos lo siguiente:mi_cursor.execute ("INSERT INTO tblArticulos(ID, Descripcion) VALUES(1, 'mouse')")
En este ejemplo estaríamos agregando el articulo “mouse” con ID “1”, a la tabla tblArticulos.
Modificar un registro
Para modificar un registro, procedemos igual que para agregarlo, pero obviamente debemos cambiar las sentencias SQL:mi_cursor.execute ("UPDATE tblArticulos SET Descripcion='Mouse Logitech MX Revolution' WHERE ID=1)")
Aquí estaríamos modificando la descripción del articulo con ID “1” (el mouse que agregamos antes).
Eliminar un registro
Una vez mas, para eliminar un registro, hacemos uso del método execute() del cursor, pasándole el código SQL correspondiente a esta tarea como parámetro:mi_cursor.execute("DELETE FROM tblArticulos WHERE ID=1)")
Aquí eliminamos el registro del articulo que creamos antes.
Consultar la base de datos
Las consultas también las hacemos con el método execute() del cursor, pero aquí nos extenderemos un poco mas en como recorrer el resultado de la consulta. Un ejemplo de consulta podría ser el siguiente:mi_cursor.execute ("SELECT * FROM tblArticulos")
Con este código, obtendríamos todos los registros de la tabla tblArticulos. Para recorrer los distintos registros que nos devolvió la consulta, podemos elegir entre los métodos fetchone(), fetchmany() y fetchall() del cursor.
1- Usando fetchone()
res = mi_cursor.fetchone()
En el objeto res tendríamos el primer registro del resultado de la consulta representado por una tupla. Cada vez que invoquemos a este método, nos dará el registro actual e internamente quedara apuntando al siguiente, de modo que si lo invocamos sucesivas veces terminaremos por recorrer todo los registros. Para recorrer todo el resultado de la consulta, podríamos escribir algo como esto:
un_registro = mi_cursor.fetchone()
while(un_registro):
print un_registro
un_registro = mi_cursor.fetchone()
2- Usando fetchmany()
fetchmany() nos devuelve una lista de tuplas con parte del resultado de la consulta, en realidad, devolverá tantos registros como nosotros le especifiquemos. Por ejemplo, si escribimos los siguiente:
res = mi_cursor.fetchmany(3)
for reg in res:
print reg
obtendríamos los tres primeros registros del resultado de la consulta; si lo ejecutamos nuevamente, obtendríamos los tres siguientes y así sucesivamente.
3- Usando fetchall()
A diferencia de fetchmany(), fetchall() retorna todos los registros del resultado de la consulta. Al igual que fetchmany(), este método también retorna una lista de tuplas. El siguiente código, mostraría todos los registros devueltos por la consulta:
res = mi_cursor.fetchall()
for reg in res:
print reg
IMPORTANTE:
Vale aclarar que si la consulta retorna una gran cantidad de registros, este método no sería el más recomendado.
También podríamos recorrer todo el resultado de la consulta, directamente sobre el cursor (sin usar ninguno de los métodos fetch):
for reg in mi_cursor:
print reg
Como hemos visto, ninguno de los métodos anteriores nos retorna la información como un diccionario, por lo que si queremos mostrar un campo concreto (digamos “ID”) de un registro, lo deberíamos especificar por el índice de la columna y no por el nombre del campo. Si necesitamos hacer uso de esta característica, podemos especificar el tipo MySQLdb.cursors.DictCursor a la hora de crear el cursor:
mi_cursor = db.cursor(MySQLdb.cursors.DictCursor)
ahora podríamos recorrer el resultado como vimos antes, pero con la salvedad de que ahora si podemos escribir cosas como estas:
for reg in mi_cursor:
print reg['ID']
con lo cual veríamos todos los IDs de los registros devueltos por la consulta.
Para terminar con este punto, les voy a hablar de una opción interesante que tenemos a la hora de pasar nuestras sentencias SQL como parámetro del método execute(). La idea es que cuando necesitamos usar variables dentro de la consulta, estas las podemos escribir de la siguiente manera:
mi_cursor.execute ("UPDATE tblArticulos SET descripción = %s WHERE id = %s", ('Mouse genérico de 3 botones', 1))
En el ejemplo puedes ver, que ahora le estamos pasando dos parámetros al método execute(), el primero sigue siendo la consulta y el segundo es una tupla de valores, que representa, en forma posicional cada uno de los %s que existen dentro de la consulta, por lo que al enviarse la consulta anterior, internamente quedaría así:
UPDATE tblArticulos SET titulo_articulo = 'Mouse genérico de 3 botones' WHERE id = 1
Como tal vez notaste, no necesitamos poner los %s entre comillas cuando su valor sea una cadena, ya que MySQLdb lo hará por nosotros.
Manejar transacciones
Cuando alteramos el contenido de nuestra base de datos (Por ejemplo: al agregar un registro), estos cambios puede que no se reflejen inmediatamente. Por ejemplo, en caso de que estemos usando tablas del tipo MyISAM, los cambios serán aplicados inmediatamente, debido a que este tipo de tablas no soportan transacciones, pero si en cambio usáramos una tabla de tipo InnoDB (que si soporta transacciones) los cambios no se reflejaran en la misma, hasta que invoquemos el método commit() de la conexión (a no ser que la característica auto-commit esta activada). Si queremos abortar una transacción, podemos usar el método rollback() de la conexión.Conclusión
En este artículo, intente hacer un paneo general por las acciones mas comunes al trabajar con una base de datos. Si bien he usado MySQL como motor de base de datos para los ejemplos, el proceso es prácticamente igual si usas otra base de datos, ya que como te comentaba al principio, gracias a DB-API, logramos una gran independencia del motor elegido. Con unos pocos cambios podrías hacer que los ejemplos funcionen con otro gestor de base de datos, solo debes instalar el driver correspondiente y luego importarlo desde tu aplicación. Los ejemplos que vimos son realmente muy triviales, es por esto que seguramente lo único que deberías modificar son los parámetros de conexión según corresponda.Para terminar, te cuento que DB-API no es la única opción para trabajar con base de datos en Python. En otra oportunidad, les hablare de los denominados ORM (motores para mapeo objeto-relacional), que nos permiten acceder a las tablas de la base de datos, como si de objetos Python se tratara. Ejemplos de ORMs son SQLObject y SQLAlchemy.
Hasta la próxima!
7 comments
Excelente post, el blog en general está muy bien, estoy aprendiendo a programar en python me ha servido de mucho, sigue así
Hola, que bueno que te sirva el material del Blog y gracias por tu aliento. Un saludo!
Perfecto, gracias!
excelente, muchas gracias!
uuuuh que bien, gracias por este post, estoy comenzando en esto de python-mysql y creo que la info publicada es de mucha utilidad, :)
Gracias, estaba loco viendo como acceder a mysql de una forma fácil en python. Al final usaré Storm, pero tu artículo me ha ido de perlas para poder buscar ORM'S.
Gracias
Lo felicito, estoy aprendiento a programar y me será de mucha utilidad.
Gracias.
Publicar un comentario