n8n con MySQL: Conecta tu Base de Datos a tus Automatizaciones

N8n con MySQL base de datos es uno de los usos más prácticos de n8n. Conectar n8n con MySQL permite que tus automatizaciones lean y escriban directamente en tu base de datos. Es la integración clave para empresas con datos en MySQL que quieren conectar esa información con emails, CRMs, hojas de cálculo u otros servicios externos.

Configurar la conexión MySQL en n8n

Requisitos previos

El servidor MySQL debe ser accesible desde n8n:

  • Si n8n está en el mismo servidor: usa localhost o 127.0.0.1
  • Si n8n está en otro servidor: abre el puerto 3306 o usa un tunnel SSH
  • Si usas MySQL en la nube (PlanetScale, Railway, etc.): tendrás un host público

Crear las credenciales MySQL en n8n

  1. Ve a CredentialsAdd Credential
  2. Busca MySQL
  3. Configura:
    • Host: IP o hostname del servidor MySQL
    • Database: nombre de la base de datos
    • User: usuario MySQL (crea uno específico con los permisos mínimos)
    • Password: contraseña
    • Port: 3306 (por defecto)
    • SSL: actívalo si tu MySQL lo requiere

Buena práctica: Crea un usuario MySQL específico para n8n con solo los permisos que necesita:

CREATE USER 'n8n_user'@'%' IDENTIFIED BY 'contraseña_segura';
GRANT SELECT, INSERT, UPDATE ON mi_base_datos.* TO 'n8n_user'@'%';
FLUSH PRIVILEGES;

Operaciones del nodo MySQL en n8n

El nodo MySQL tiene dos modos principales:

Execute Query: SQL libre, cualquier operación
Insert: Inserta filas de forma segura (sin SQL manual)

Usa Execute Query para SELECTs y operaciones complejas, e Insert para añadir datos de forma más segura.

Caso de uso 1: Sincronizar MySQL con Google Sheets

Exporta datos de MySQL a Google Sheets para que tu equipo pueda analizarlos sin acceso directo a la base de datos:

Schedule Trigger (cada día a las 7:00)
  → MySQL — Execute Query (SELECT)
  → Google Sheets — Clear (limpiar hoja)
  → Google Sheets — Append (añadir datos)

Query de ejemplo:

SELECT
  c.id,
  c.nombre,
  c.email,
  c.empresa,
  COUNT(p.id) as total_pedidos,
  SUM(p.importe) as total_gastado,
  MAX(p.fecha) as ultimo_pedido
FROM clientes c
LEFT JOIN pedidos p ON c.id = p.cliente_id
GROUP BY c.id
ORDER BY total_gastado DESC
LIMIT 1000

Caso de uso 2: Alertas de datos anómalos

Monitoriza tu base de datos y envía alertas cuando algo es inusual:

Schedule Trigger (cada 15 minutos) →

  1. MySQL — consulta por pedidos sin procesar en más de 2 horas
  2. IF — si hay resultados (count > 0)
  3. Slack — alerta al equipo de operaciones

Query de alerta:

SELECT COUNT(*) as pedidos_bloqueados
FROM pedidos
WHERE estado = 'pendiente'
  AND created_at < DATE_SUB(NOW(), INTERVAL 2 HOUR)
  AND notificacion_enviada = 0

Actualizar flag tras enviar la alerta:

UPDATE pedidos
SET notificacion_enviada = 1
WHERE estado = 'pendiente'
  AND created_at < DATE_SUB(NOW(), INTERVAL 2 HOUR)

Caso de uso 3: Registrar datos de formularios web

Guarda directamente en MySQL los datos de formularios externos:

Webhook (formulario de contacto)
  → MySQL — Insert
  → Gmail — Confirmación al usuario

Nodo MySQL — Insert:

  • Table: contactos
  • Columns: nombre, email, mensaje, ip, created_at
  • Data:
    nombre: {{ $json.body.nombre }}
    email: {{ $json.body.email }}
    mensaje: {{ $json.body.mensaje }}
    ip: {{ $json.headers['x-forwarded-for'] }}
    created_at: {{ $now.toSQL() }}
    

Caso de uso 4: Reportes automáticos por email

Envía reportes SQL por email cada semana al equipo directivo:

Schedule Trigger (lunes 8:30) →

  1. MySQL — múltiples queries de resumen
  2. Code — formatea los datos en HTML
  3. Gmail — envía el informe

Ejemplo de queries del informe:

-- Ventas de la semana
SELECT
  DATE(fecha) as dia,
  COUNT(*) as pedidos,
  SUM(importe) as ingresos
FROM pedidos
WHERE fecha >= DATE_SUB(NOW(), INTERVAL 7 DAY)
GROUP BY DATE(fecha)
ORDER BY dia
// Nodo Code: genera HTML del informe
const rows = $input.all();
const table = rows.map(r =>
  `<tr><td>${r.json.dia}</td><td>${r.json.pedidos}</td><td>${r.json.ingresos}€</td></tr>`
).join('');

return [{
  html: `
    <h2>Informe semanal de ventas</h2>
    <table border="1">
      <tr><th>Día</th><th>Pedidos</th><th>Ingresos</th></tr>
      ${table}
    </table>
  `
}];

Caso de uso 5: Migración de datos entre sistemas

Sincroniza datos de un sistema legacy en MySQL con tu nuevo CRM:

Schedule Trigger (cada hora)
  → MySQL — SELECT (registros nuevos desde última sincronización)
  → Loop
    → HubSpot — Upsert Contact
    → MySQL — UPDATE (marca como sincronizado)

Consulta de registros pendientes:

SELECT *
FROM clientes_legacy
WHERE sincronizado = 0
   OR updated_at > (SELECT MAX(sync_time) FROM sync_log WHERE target = 'hubspot')
LIMIT 100

Seguridad: Evitar SQL injection en n8n

Al usar Execute Query con datos del usuario, usa parámetros en lugar de concatenar strings:

-- ❌ Inseguro
SELECT * FROM usuarios WHERE email = '{{ $json.email }}'

-- ✅ Seguro: usa el campo "Query Parameters" del nodo MySQL
SELECT * FROM usuarios WHERE email = ?

En el campo Query Parameters del nodo MySQL, añade el valor {{ $json.email }}. n8n lo pasa como parámetro preparado, evitando SQL injection.

Conclusión

La integración n8n con MySQL convierte tu base de datos en un participante activo de tus flujos de trabajo. Ya sea para sincronizar datos, enviar alertas basadas en queries o generar informes automáticos, n8n hace que tu MySQL se conecte con el resto de herramientas de tu empresa de forma segura y sencilla.