jueves, 7 de abril de 2011

Consultando mysql desde bash

No es muy común que necesitemos consultar bases de datos mysql desde un shellscript, pero en ciertas ocasiones (por ejemplo en un cron), podemos desear hacerlo. Ya sea para registrar un backup en una tabla de logs o tomar algún dato necesario para nuestro script desde una tabla, puede suceder que desde bash necesitemos consultar a mysql sin querer usar un script intermediario hecho en otro lenguaje, como perl o php.


¿Cómo accedemos?


Para acceder a la base de datos utilizaremos el CLI de mysql y lo iniciaremos con dos parámetros:

  • -B Hace que el cliente CLI de mysql trabaje en modo batch entonces, en lugar de devolver los datos en tablas dibujadas en ascii, devolverá los resultados separando los campos por tabuladores y los registros por nuevas líneas. Además no muestra prompt.

  • -N Evita que el CLI de mysql devuelva los headers con los nombres de los campos



Ejemplo



mysql -N -B

Nota:Me centraré en las consultas select, las consultas de modificación se ejecutan fácilmente utilizando el parámetro -e de mysql CLI y especificando la consulta de modificación.

Luego debemos asegurarnos que el CLI de mysql reciba nuestras consultas, pero como no las tipearemos nosotros en el prompt, tenemos que redirigir nuestras consultas a su entrada estándar para que las reciba, esto se puede hacer fácilmente mediante echo y haciendo entubamiento hacia mysql. Además le indico a mysql el nombre de la base de datos en la que debe consultar.



Ejemplo



echo "SELECT * FROM mi_tabla WHERE 1" | mysql -N -B mi_base_de_datos

El siguiente paso es hacer que el resultado quede guardado en una variable, para esto utilizamos las comillas invertidas.



Ejemplo



RESULTADOS=`echo "SELECT * FROM mi_tabla WHERE 1" | mysql -N -B mi_base_de_datos`

Ahora ya tenemos los resultados de nuestra consulta en una variable y lo único que debemos hacer es parsearlos. Para esto debemos hacer uso de la variable especial IFS de bash, la cual indica el separador que se utiliza para delimitar tokens al usar programas como for o awk, seteándole qué caracter debe usar para dividir las cadenas. En nuestro caso '\n' para separar registros y '\t' para separar campos.


En este post intentaré hacer todo lo más simplificado posible para que sea claro y entendible, por lo que indicaremos en la consulta qué campos deseamos de la tabla para saber su orden.



El ejemplo completo


Los comentarios explican lo que hace el script.

DBUSER=mi_user
DBPASS=mi_pass
RES=`echo "SELECT id, nombre FROM mi_tabla WHERE 1;" | mysql -N -B -u $DBUSER -p$DBPASS mi_db` # Ejecuto la consulta y la guardo en RES
OLDIFS="$IFS" # Respaldo el valor de IFS, no olvidar las comillas dobles
IFS=$'\n' # Seteo el valor de IFS que me sirve
for row in $RES ; # Itero por los registros porque for separará por \n
do
if [ ${#row} -gt 0 ]; then # Chequeo si tengo un registro
INNERIFS="$IFS" # Hago un respaldo temporal de IFS, no olvidar las comillas dobles
IFS="$OLDIFS" # Ahora separaré los campos

id=$(echo $row | awk '{print $1}') # Utilizo awk porque sé el orden de los campos: id es el 1 y nombre es el 2
nombre=$(echo $row | awk '{print $2}')

echo "El id es $id y el nombre es $nombre"
IFS="$INNERIFS" # Vuelvo a hacer que IFS separe por \n para la próxima iteración
fi
done

IFS="$OLDIFS" # Dejo IFS en su estado original.

Como se ve es bastante fácil acceder a los datos, utilizando este esquema se pueden parsear resultados aun más complejos, es cuestión de experimentar un poco.

5 Comentários:

Anónimo dijo...

Muchas gracias!!

Anónimo dijo...

Me gustaría saber como envío la salida a un archivo, lo ejecuto tal como está allí y no hace nada.

Ing. Jesús Uzcanga dijo...

EXCELENTE!!!

Muchas Gracias por publicar info útil.

Anónimo dijo...

Excelente aporte, muchas gracias

Anónimo dijo...

Supremo aporte, mil gracias por publicar esto

Publicar un comentario

Epistemomaniáticos ©Template Blogger Green by Dicas Blogger.

TOPO