Acción: MySQL (mysql)¶
Este nodo permite que una automatización consulte, inserte, actualice o elimine datos en una base de datos MySQL. Se usa para registrar eventos de seguridad, leer listas de acceso, actualizar estados de visitas, auditar actividad de dispositivos o ejecutar cualquier operación SQL contra una base de datos existente en la instalación.
Capturas de pantalla¶
El nodo en el canvas de automatizaciones¶

① Trigger que inicia el flujo · ② Nodo anterior (ejemplo: S3 API) · ③ Nodo MySQL — doble click para configurarlo
Formulario de configuración¶

① Selector de credencial MySQL (host, puerto, base de datos, usuario, contraseña) · ② Conexión SSL · ③ Acción a ejecutar · Área cyan: campos que cambian según la acción · Test to Here: probar el nodo sin ejecutar el flujo completo
Las 6 acciones disponibles¶

¿Cuándo usarlo?¶
- Cuando una automatización debe registrar alarmas o eventos en una base de datos MySQL del cliente.
- Cuando necesitás consultar una lista de accesos autorizados para validar permisos dentro del flujo.
- Cuando querés actualizar el estado de una visita (activa, completada, rechazada) en tiempo real.
- Cuando un flujo de auditoría requiere insertar logs de actividad de cámaras, sensores o puertas.
- Cuando necesitás sincronizar datos entre NetSocs y un sistema externo que usa MySQL (ERP, RRHH, control de acceso legacy).
- Cuando un nodo de IA generó resultados que deben persistirse en una tabla para reportes posteriores.
- Cuando querés ejecutar una query SQL compleja que no entra en los patrones simples de insert/update.
¿Cuándo NO usarlo? Si solo necesitás almacenar datos temporales dentro del flujo, usá el nodo Set Memory en cambio. Si la base de datos es PostgreSQL, MongoDB o Redis, usá el nodo de agente con tool de base de datos correspondiente.
Cómo configurarlo¶
Paso 0) Abrir la parametrización¶
- En el canvas, hacé doble click sobre el nodo MySQL.
- Se abre un panel con dos pestañas: Form (recomendada) y JSON Editor (para usuarios avanzados).
- El botón Test to Here permite ejecutar el flujo hasta este nodo sin continuar al siguiente — útil para verificar la conexión y los datos devueltos.
Paso 1) Configurar las credenciales¶
El nodo requiere una credencial de tipo MySQL que almacena de forma segura:
| Campo | Descripción | Ejemplo |
|---|---|---|
| Host | IP o hostname del servidor MySQL | 192.168.1.50 |
| Port | Puerto del servidor (por defecto: 3306) | 3306 |
| Database | Nombre de la base de datos a la que conectar | netsocs_eventos |
| Username | Usuario con permisos sobre la base de datos | app_user |
| Password | Contraseña del usuario | •••••••• |
- Usá el selector de credenciales para elegir una credencial existente o crear una nueva haciendo click en + Nueva credencial.
- Las credenciales se almacenan cifradas y son reutilizables en múltiples nodos.
Nunca ingreses las credenciales directamente en el JSON Editor como texto plano.
Paso 2) Use SSL¶
Activá el switch Use SSL si tu servidor MySQL requiere conexión cifrada (TLS/SSL).
| Estado | Cuándo usarlo |
|---|---|
| Apagado | Servidor MySQL en red interna sin SSL (instalaciones on-premise típicas) |
| Encendido | Servidor MySQL en la nube (RDS, Cloud SQL, PlanetScale) o que exija TLS |
Paso 3) Elegir la acción¶
El campo Action define qué operación ejecuta el nodo. Los campos del formulario cambian automáticamente según la acción elegida.
| Acción | Qué hace |
|---|---|
| Select Rows | Consulta filas de una tabla con filtros opcionales |
| Insert Rows | Inserta una o más filas nuevas en una tabla |
| Insert or Update Rows | Upsert: inserta si no existe, actualiza si ya existe |
| Update Rows | Actualiza filas existentes que cumplan una condición |
| Delete Table or Rows | Elimina filas que cumplan una condición, o toda la tabla |
| Execute SQL Query | Ejecuta cualquier consulta SQL escrita a mano (modo avanzado) |
Paso 4) Completar los campos según la acción¶
Select Rows — Consultar filas¶
| Campo | Descripción | Ejemplo |
|---|---|---|
| Table Name | Nombre de la tabla a consultar | eventos_alarma |
| Where Clause | Condición SQL para filtrar filas (sin la palabra WHERE) |
zona = 'norte' AND activo = 1 |
| Order By | Columna y dirección de ordenamiento | created_at DESC |
| Limit | Máximo de filas a devolver (0 = sin límite) | 100 |
La respuesta incluye el array
rowscon los registros encontrados.
Insert Rows — Insertar filas¶
| Campo | Descripción | Ejemplo |
|---|---|---|
| Table Name | Nombre de la tabla donde insertar | visitas |
| Rows | Array JSON con los objetos a insertar (uno por fila) | [{"nombre": "Juan", "zona": "acceso_norte"}] |
La respuesta incluye
last_insert_idcon el ID del último registro insertado.
Insert or Update Rows — Upsert¶
| Campo | Descripción | Ejemplo |
|---|---|---|
| Table Name | Nombre de la tabla | dispositivos |
| Rows | Array JSON con los objetos a insertar o actualizar | [{"id": 5, "estado": "online", "ultima_vez": "2024-01-01"}] |
Requiere que la tabla tenga una clave primaria o índice único para determinar si insertar o actualizar.
Update Rows — Actualizar filas¶
| Campo | Descripción | Ejemplo |
|---|---|---|
| Table Name | Nombre de la tabla | visitas |
| Where | Condición para identificar qué filas actualizar | id = 42 |
| Set | Objeto JSON con los campos y valores nuevos a aplicar | {"estado": "completada", "salida": "2024-05-06 18:00"} |
La respuesta incluye
rows_affectedcon el número de filas modificadas.
Delete Table or Rows — Eliminar filas o tabla¶
| Campo | Descripción | Ejemplo |
|---|---|---|
| Table Name | Nombre de la tabla | logs_temporales |
| Where | Condición para filtrar qué filas eliminar (vacío = todas) | created_at < '2024-01-01' |
Peligro: si no especificás una condición Where, se eliminan todas las filas de la tabla. En el JSON Editor,
drop_table: trueelimina la tabla completa (irreversible).
Execute SQL Query — Query libre¶
| Campo | Descripción | Ejemplo |
|---|---|---|
| SQL Query | Consulta SQL completa para ejecutar | SELECT zona, COUNT(*) as total FROM alarmas GROUP BY zona |
Usá esta acción solo cuando las opciones anteriores no cubran el caso. Cualquier consulta válida de MySQL es aceptada.
Buenas prácticas¶
- Usá credenciales con permisos mínimos: si el nodo solo lee datos, la credencial no necesita permisos de escritura ni DDL.
- Siempre especificá Where en updates y deletes: un update o delete sin condición afecta a toda la tabla.
- Usá Limit en Select Rows: en tablas con miles de registros, un select sin límite puede hacer lento el flujo o agotar memoria.
- Probá con "Test to Here" antes de activar el flujo: verificá que la conexión funciona y que la query devuelve lo esperado.
- Para Insert or Update, asegurate de tener clave primaria: sin un índice único, la operación de upsert puede insertar duplicados.
- En Execute SQL Query, evitá queries destructivas: preferí las acciones específicas (Delete, Update) porque tienen validaciones de campo.
- Separar credenciales por ambiente: usá una credencial para producción y otra para desarrollo/testing.
- Activá SSL para servidores en la nube: RDS, Cloud SQL y similares suelen requerir TLS.
Troubleshooting (problemas comunes)¶
- "table_name is required for action 'select_rows'"
-
El campo Table Name está vacío. Completalo con el nombre exacto de la tabla antes de guardar o probar.
-
El nodo falla con error de autenticación (Access denied)
- Verificá que el usuario y contraseña en la credencial sean correctos.
- Asegurate de que el usuario tenga permisos para la operación en esa base de datos:
GRANT SELECT ON db.* TO 'usuario'@'%'. -
Confirmá que el servidor MySQL permita conexiones desde la IP del servidor de automatizaciones.
-
El nodo falla con "Can't connect" o timeout
- Verificá que el Host y Port sean correctos y accesibles desde el servidor de automatizaciones.
- Comprobá que el firewall de la instalación permita tráfico en el puerto 3306 (u otro configurado).
-
Si el servidor MySQL está en la misma red, probá con la IP interna en vez del hostname.
-
Select Rows devuelve array vacío pero la tabla tiene datos
- Revisá la condición Where Clause: puede que sea demasiado restrictiva o tenga una comparación de tipos incorrecta.
-
Verificá que el usuario tenga permisos de
SELECTsobre la tabla específica. -
Insert falla con "Duplicate entry"
- La tabla tiene una restricción de unicidad (PRIMARY KEY o UNIQUE) y estás intentando insertar un valor ya existente.
-
Usá Insert or Update Rows (upsert) para manejar este caso automáticamente.
-
Update no modifica ninguna fila (rows_affected: 0)
-
La condición Where no coincide con ningún registro. Verificá los valores de la condición.
-
El nodo falla con "SSL required" o similar
- Activá el switch Use SSL en el formulario.
Configuración avanzada (JSON Editor) — solo usuarios expertos¶
La pestaña JSON Editor permite ver y editar directamente la estructura completa del nodo. Útil para copiar configuraciones entre flujos.
Estructura completa del input¶
{
"host": "/**$credential(\"host\", 2)**/",
"port": "/**$credential(\"port\", 2)**/",
"database": "/**$credential(\"database\", 2)**/",
"username": "/**$credential(\"username\", 2)**/",
"password": "/**$credential(\"password\", 2)**/",
"use_ssl": false,
"action": "select_rows",
"table_name": "eventos_alarma",
"where_clause": "zona = 'norte'",
"order_by": "created_at DESC",
"limit": 50,
"where": "",
"rows": [],
"set": {},
"drop_table": false,
"query": ""
}
Tabla de todos los campos¶
| Campo | Tipo | Requerido por | Descripción |
|---|---|---|---|
host |
string |
Siempre | IP/hostname del servidor (referencia a credencial) |
port |
string |
Siempre | Puerto del servidor (referencia a credencial) |
database |
string |
Siempre | Nombre de la base de datos (referencia a credencial) |
username |
string |
Siempre | Usuario MySQL (referencia a credencial) |
password |
string |
Siempre | Contraseña (referencia a credencial) |
use_ssl |
boolean |
Opcional | true para conexión cifrada TLS/SSL |
action |
string |
Siempre | Una de las 6 acciones disponibles |
table_name |
string |
Todas menos execute_sql_query |
Nombre de la tabla sobre la que operar |
where_clause |
string |
select_rows |
Condición SQL sin la palabra WHERE |
order_by |
string |
select_rows |
Columna y dirección de ordenamiento |
limit |
number |
select_rows |
Máximo de filas a devolver. 0 = sin límite |
where |
string |
delete_table_or_rows, update_rows |
Condición de filtro para delete o update |
rows |
array |
insert_rows, insert_or_update_rows |
Array de objetos con los datos a insertar |
set |
object |
update_rows |
Objeto con los campos y valores a actualizar |
drop_table |
boolean |
delete_table_or_rows |
true para eliminar la tabla completa (irreversible) |
query |
string |
execute_sql_query |
Query SQL completa a ejecutar |
Los campos
host,port,database,usernameypasswordson referencias a credenciales cuando se configuran desde el formulario. No pongas estos valores como texto plano en el JSON.
Estructura de la respuesta¶
{
"success": true,
"rows_affected": 3,
"rows": [
{ "id": 1, "zona": "norte", "created_at": "2024-05-06 10:00:00" }
],
"last_insert_id": 42
}
| Campo | Cuándo aparece | Descripción |
|---|---|---|
success |
Siempre | true si la operación fue exitosa |
rows |
select_rows, execute_sql_query |
Array con los registros devueltos |
rows_affected |
insert_rows, update_rows, delete_* |
Número de filas afectadas por la operación |
last_insert_id |
insert_rows, insert_or_update_rows |
ID del último registro insertado |
Ejemplos JSON por caso de uso¶
Consultar últimas 10 alarmas de zona norte¶
{
"host": "/**$credential(\"host\", 2)**/",
"port": "/**$credential(\"port\", 2)**/",
"database": "/**$credential(\"database\", 2)**/",
"username": "/**$credential(\"username\", 2)**/",
"password": "/**$credential(\"password\", 2)**/",
"use_ssl": false,
"action": "select_rows",
"table_name": "alarmas",
"where_clause": "zona = 'norte' AND resuelta = 0",
"order_by": "created_at DESC",
"limit": 10
}
Registrar evento de acceso denegado¶
{
"host": "/**$credential(\"host\", 2)**/",
"port": "/**$credential(\"port\", 2)**/",
"database": "/**$credential(\"database\", 2)**/",
"username": "/**$credential(\"username\", 2)**/",
"password": "/**$credential(\"password\", 2)**/",
"use_ssl": false,
"action": "insert_rows",
"table_name": "log_accesos",
"rows": [
{
"persona": "Juan Perez",
"puerta": "acceso_principal",
"resultado": "denegado",
"motivo": "credencial_expirada",
"timestamp": "2024-05-06 14:32:00"
}
]
}
Marcar visita como completada¶
{
"host": "/**$credential(\"host\", 2)**/",
"port": "/**$credential(\"port\", 2)**/",
"database": "/**$credential(\"database\", 2)**/",
"username": "/**$credential(\"username\", 2)**/",
"password": "/**$credential(\"password\", 2)**/",
"use_ssl": false,
"action": "update_rows",
"table_name": "visitas",
"where": "id = 42",
"set": {
"estado": "completada",
"hora_salida": "2024-05-06 18:00:00"
}
}
Limpiar logs anteriores a 2024¶
{
"host": "/**$credential(\"host\", 2)**/",
"port": "/**$credential(\"port\", 2)**/",
"database": "/**$credential(\"database\", 2)**/",
"username": "/**$credential(\"username\", 2)**/",
"password": "/**$credential(\"password\", 2)**/",
"use_ssl": false,
"action": "delete_table_or_rows",
"table_name": "logs_sistema",
"where": "created_at < '2024-01-01'"
}
Reporte de alarmas por zona (query libre)¶
{
"host": "/**$credential(\"host\", 2)**/",
"port": "/**$credential(\"port\", 2)**/",
"database": "/**$credential(\"database\", 2)**/",
"username": "/**$credential(\"username\", 2)**/",
"password": "/**$credential(\"password\", 2)**/",
"use_ssl": false,
"action": "execute_sql_query",
"query": "SELECT zona, COUNT(*) as total, MAX(created_at) as ultima FROM alarmas WHERE resuelta = 0 GROUP BY zona ORDER BY total DESC"
}
Guías rápidas (recetas)¶
Receta A — "Registrar alarma en BD al dispararse un sensor"¶
- Trigger: estado de sensor cambia a "alarma"
- Action:
Insert Rows - Table Name:
alarmas - Rows:
[{"zona": "norte", "sensor_id": "SEN-001", "tipo": "movimiento", "created_at": "{{timestamp}}"}] - Resultado: cada activación del sensor queda registrada en la BD con fecha y datos del sensor
Receta B — "Verificar si una persona tiene acceso antes de abrir puerta"¶
- Trigger: lectura de tarjeta o QR
- Action:
Select Rows - Table Name:
personas_autorizadas - Where Clause:
tarjeta_id = '{{id_tarjeta}}' AND activo = 1 - Limit:
1 - Resultado: si
rowsdevuelve un registro → continuar al nodo de apertura; si está vacío → denegar
Receta C — "Sincronizar estado de dispositivo con sistema externo"¶
- Trigger: cambio de estado de dispositivo en NetSocs
- Action:
Insert or Update Rows - Table Name:
dispositivos_sync - Rows:
[{"device_id": "{{id}}", "estado": "{{estado}}", "ultima_actualizacion": "{{timestamp}}"}] - Resultado: el estado siempre refleja el último valor sin generar duplicados
Receta D — "Cerrar visita automáticamente al detectar salida"¶
- Trigger: evento de salida en puerta principal
- Action:
Update Rows - Table Name:
visitas - Where:
persona_id = '{{id}}' AND estado = 'activa' - Set:
{"estado": "cerrada", "hora_salida": "{{timestamp}}"} - Resultado: la visita queda cerrada en la BD cuando el sistema detecta la salida física
Receta E — "Limpiar registros temporales de procesamiento de IA"¶
- Trigger: schedule diario a las 3:00 AM
- Action:
Delete Table or Rows - Table Name:
resultados_temporales_ia - Where:
created_at < DATE_SUB(NOW(), INTERVAL 7 DAY) - Resultado: los registros de más de 7 días se eliminan automáticamente sin intervención manual
Receta F — "Generar reporte de accesos por turno"¶
- Trigger: schedule al final de cada turno (6:00, 14:00, 22:00)
- Action:
Execute SQL Query - Query:
SELECT puerta, COUNT(*) as accesos, SUM(resultado = 'denegado') as denegados FROM log_accesos WHERE timestamp BETWEEN '{{inicio_turno}}' AND '{{fin_turno}}' GROUP BY puerta - Resultado: el array
rowscontiene el resumen del turno, listo para enviar por email o guardar en S3
Referencias internas¶
- Key del nodo:
mysql - Clase:
action - Campos siempre requeridos:
host,database,username,password,action - Credencial requerida: tipo
mysql(host, port, database, username, password) - Puerto por defecto:
3306 - SSL: opcional, activar para servidores en la nube o que exijan TLS
- Bases de datos compatibles: MySQL 5.7+, MySQL 8.x, MariaDB 10.x+, PlanetScale, Amazon RDS MySQL, Google Cloud SQL MySQL