MySQL: Cómo ejecutar consultas desde un Shell Script

Publicado por Diego Córdoba en

Hoy les voy a comentar brevemente cómo podemos conectar a una base de datos y realizar algunas consultas desde terminal y, por supuesto, desde nuestros shell scripts.

Bash Scripts y las bases de datos

Este artículo surge para ampliar la respuesta a una consulta que me hizo un alumno del curso de Shell Scripting con Bash en Linux, sobre cómo realizar consultas a una base de datos SQL desde un script.

La mayoría de los lenguajes de programación proveen mecanismos que nos permiten acceder a una base de datos para realizar consultas/queries de manera sencilla.

Shell scripting, particularmente bash, no provee mecanismos nativos para realizar las conexiones y consultas, se fundamenta en los clientes de línea de comandos que podemos ejecutar.

Recordemos que un shell script es una extensión de la línea de comandos, que nos permite realizar tareas por lotes, «programándolas» dentro de un archivo de texto llamado script.

Por lo tanto no hay magia aquí: si desde terminal podemos ejecutar un comando mysql o mariadb para conectar a una base de datos, autenticarnos y realizar alguna consulta, también podemos colocar dicho comando dentro de un script para que la tarea se realice automáticamente cuando corramos el script.

Autenticando con la línea de comandos

Quienes trabajamos o hemos trabajado con bases de datos en Linux, particularmente con MariaDB o Mysql, sabemos que disponemos de un comando mysql para poder conectarnos a un servidor y obtener una terminal interactiva, una shell dentro del servidor SQL, donde poder realizar consultas.

El comando de conexión es algo similar a esto:

mysql -u USUARIO -pCONTRASEÑA
o
mysql --user=USUARIO --password=CONTRASEÑA

Se puede especificar la password también en este comando, pero no es conveniente, por razones de seguridad… salvo que, por supuesto, necesitemos ejecutar un comando no interactivo 😛

El comando mysql provee una opción muy interesante para este caso: -e.

Esta opción permite ejecutar una consulta sobre la base de datos a la cual nos estamos conectando, y es la base de lo que podemos hacer en una base de datos desde un shell script, o desde nuestra línea de comandos, claro.

mysql -u USUARIO -pCONTRASEÑA -e "CONSULTA SQL"

Aquí, -pCONTRASEÑA no es un error de tipeo, no debe haber espacio entre el -p y la password del usuario. En su defecto se puede usar la otra notación: --password=CONTRASEÑA.

También podemos seleccionar una base de datos sobre la cual aplicar la consulta:

mysql -u USUARIO -pCONTRASEÑA -D BASE_DE_DATOS -e "CONSULTA SQL"

Aquí hemos usado la opción -D para especificar el nombre de la base de datos donde aplicar la consulta.

Si el servidor se encuentra en otro host, también podríamos especificar la IP del mismo usando -h:

mysql -u USUARIO -pCONTRASEÑA -h HOSTNAME_O_IP -e "CONSULTA SQL"

Para este caso particular, el usuario con el que intentamos autenticar debe estar habilitado para conectarse desde el equipo remoto, por supuesto.

Y desde ya, como cualquier comando en Linux, se pueden combinar estas opciones.

Las opciones mencionadas, y otras opciones que pueden sernos muy útiles cuando trabajamos con bases de datos en un script son:

  • -u | --user: para especificar el nombre de usuario de login.
  • -p | --password: para especificar la contraseña del usuario.
  • -D | --database: para especificar el nombre de la base de datos a utilizar.
  • -h | --host: para especificar el host donde queremos conectarnos.
  • -N | --skip-column-names: para no mostrar los encabezados de columnas en la salida.
  • -B | --batch: para mostrar tabuladores para separar columnas en la salida.

Otras facilidades para shell scripting y terminal

Otras herramientas que pueden ayudarnos en el trabajo con bases de datos SQL en shell scripting son las siguientes:

Leyendo consultas desde un archivo .sql

Si tenemos un archivo SQL, por ejemplo, un dump de datos, y queremos incorporarlo en nuestro servidor, podemos hacerlo con un comando mysql y una redirección de entrada:

mysql -u USUARIO -pCONTRASEÑA < /ruta/al/dump.sql

Este comando conectará a la base de datos, y ejecutará todas las sentencias incluidas en dump.sql. Aquí se pueden usar cualquiera de las opciones adicionales del comando, como -h para especificar la iP del servidor, o -D para especificar la base de datos donde aplicar los cambios.

Escribiendo la salida en un archivo de texto

Si estamos realizando una consulta de datos a una base de datos, y necesitamos exportar dichos datos a un archivo para procesarlos en otro momento, podemos simplemente usar una redirección de salida de terminal de esta forma:

mysql -u USUARIO -pCONTRASEÑA  -e "CONSULTA SQL" > /ruta/salida.txt

Escribiendo varias consultas en un mismo comando mysql

Finalmente, otro «truco» que podemos usar para ejecutar varias consultas SQL en un mismo comando, sin necesidad de leerlas desde un archivo, es crear un «archivo virtual» delimitado durante la ejecución del comando, utilizando la redirección <<.

A esto se lo denomina «Here Document», o «heredoc», y es válido para cualquier comando, no solo mysql.

Aquí un ejemplo:

mysql -u USUARIO -pCONTRASEÑA <<EOF
CONSULTA SQL 1;
CONSULTA SQL 2;
CONSULTA SQL 3;
CONSULTA SQL 4;
EOF

Aquí la palabra EOF representa «End of File» y es una convención, pero no necesariamente debe ser esa… podría ser, por ejemplo, FIN_CONSULTA. Lo importante es repetir la misma palabra luego del << y al final de las consultas en una línea nueva.

Esto va a producir que el comando mysql lea la consulta desde terminal, y finalice su lectura cuando encuentra la palabra de fin de archivo especificada luego de <<.

Por ejemplo:

#!/usr/bin/bash
mysql -u root -psupersecreto <<LISTADO
USE basedatos;
SHOW tables;
LISTADO

Si lo que estamos incluyendo contiene tabuladores y deseamos eliminarlos antes de enviarlos al comando, podemos anteponer un - delante de la palabra de cierre de archivo.

#!/usr/bin/bash
mysql -u root -psupersecreto <<-LISTADO
USE basedatos;
        SHOW tables;
LISTADO

El - eliminará el tabulador delante de SHOW.

Heredoc en shell scripting tiene muchísimas cualidades interesantes, pero eso ya escapa a este artículo.

Enviando una consulta por pipe a mysql

Otra forma interesante de enviar una consulta al comando mysql es utilizando el pipe | de esta forma:

echo "CONSULTA SQL;" |  mysql -u USUARIO -pCONTRASEÑA -D BASE_DE_DATOS

Y esto con cualquier tipo de consulta, INSERT, UPDATE, DELETE, etc.

También se puede leer un archivo .sql y enviarlo por pipe al comando:

cat /ruta/dump.sql | mysql -u USUARIO -pCONTRASEÑA -D BASE_DE_DATOS

Leyendo un csv e insertando datos en una base de datos

Algo interesante: si tenemos un archivo csv con un montón de datos y queremos programar un shell script que convierta esas líneas en sentencias INSERT para añadir a la base de datos, podríamos usar algo como esto:

#!/usr/bin/env bash

IFS=','
cat datos_alumnos.csv | while read id nombre apellido domicilio telefono; do
    echo "INSERT INTO colegio.alumnos (ID,NOMBRE,APELLIDO,DOMICILIO,TELEFONO) VALUES ('$id','$nombre','$apellido','$domicilio','$telefono');"
done | mysql --user=USUARIO --password=CONTRASEÑA

Aquí configuramos el separador de columnas como una coma usando la variable IFS (Internal Field separator). Luego leemos el contenido del csv, y mostramos consultas INSERT con los datos de cada una de las líneas reemplazados. Esas consultas se muestran en la salida estandar. Luego tomamos esa salida estándar y la enviamos al comando mysql que ejecuta todas las consultas.

Otra forma de lograr esto es usando LOAD DATA en mysql:

$ mysql --user=USUARIO --password=CONTRASEÑA colegio << EOF
> LOAD DATA INFILE '$HOME/datos_alumnos.csv' INTO TABLE alumnos FIELDS TERMINATED BY ',';
> EOF

Conclusión

Y hemos llegado al final!

Hemos realizado una breve reseña de algunos tips que pueden sernos útiles al momento de trabajar con bases de datos Mysql/MariaDB desde nuestra línea de comandos y, por consiguiente, desde nuestros shell scripts.

Espero que les sirva! Hasta la próxima!


¿Preguntas? ¿Comentarios?

Si tenés dudas, o querés dejarnos tus comentarios y consultas, sumate al grupo de Telegram de la comunidad JuncoTIC!
¡Te esperamos!

Categorías: Linux

Diego Córdoba

- Ingeniero en Informática - Mg. Teleinformática - Tesis pendiente - Docente universitario - Investigador