DEV Community

Pirate Prentice
Pirate Prentice

Posted on

n8n MySQL Node: Query, Insert, Update, and Delete Records (Free Workflow JSON)

MySQL powers WordPress, Shopify storefronts, Laravel apps, and countless internal business tools. The n8n MySQL node lets you read from and write to any MySQL (or MariaDB) database inside your automation workflows, without writing connection boilerplate.

This guide covers credential setup, every operation the node supports, the gotchas that trip people up, and a free workflow JSON you can import today.


What the n8n MySQL Node Can Do

Operation What it does
Execute Query Run any raw SQL — SELECT, INSERT, UPDATE, DELETE, or stored procedures
Insert Insert one or more rows from workflow data
Update Update rows matching a WHERE column value
Delete Delete rows matching a WHERE column value
Execute Stored Procedure Call a named stored procedure with parameters

For most use cases, Execute Query is the most flexible option. The dedicated Insert/Update/Delete operations are convenient for simple single-table writes, but Execute Query handles joins, transactions, and complex WHERE clauses that the simplified operations cannot.


Credential Setup

In n8n, go to Credentials → New → MySQL. You need:

  • Host — your database host (e.g., db.example.com or 127.0.0.1)
  • Database — the database name
  • User and Password
  • Port — default 3306
  • SSL — toggle on for cloud databases (required for PlanetScale, Railway, AWS RDS, Google Cloud SQL)

Common gotcha: Cloud MySQL providers require SSL. Toggle SSL on and set Verify server certificate based on whether you have a CA cert. If you get a connection error on a cloud database, SSL is almost always the first thing to check.

MariaDB: The MySQL node works with MariaDB too — use the same credential type. Newer MariaDB versions may need allowPublicKeyRetrieval: true if you see authentication plugin errors.


Execute Query — Raw SQL

The most powerful operation. Use it for anything the simplified operations cannot handle.

Simple SELECT:

SELECT id, email, created_at FROM users WHERE status = 'active' LIMIT 100;
Enter fullscreen mode Exit fullscreen mode

Parameterized query (recommended — prevents SQL injection):

SELECT * FROM orders WHERE customer_id = ? AND status = ?
Enter fullscreen mode Exit fullscreen mode

With Query Parameters set to: ={{ $json.customer_id }},{{ $json.status }}

Always use ? placeholders and pass values through Query Parameters rather than interpolating them directly into the SQL string. This prevents SQL injection and handles escaping automatically.

INSERT with returning the new ID:

INSERT INTO leads (email, source, created_at) VALUES (?, ?, NOW())
Enter fullscreen mode Exit fullscreen mode

The node returns { affectedRows: 1, insertId: 42 } — use {{ $json.insertId }} in the next node.

UPDATE multiple columns:

UPDATE contacts SET last_seen = NOW(), status = ? WHERE id = ?
Enter fullscreen mode Exit fullscreen mode

Insert Operation

The Insert operation lets you map workflow fields to table columns without writing SQL.

  1. Set Operation to Insert
  2. Set Table to your target table name
  3. Under Columns, map each column to a workflow expression: email → {{ $json.email }}

This is the fastest path for simple single-table inserts. For batch inserts from a list, combine with Split In Batches upstream to avoid hitting MySQL's max_allowed_packet limit.


Update Operation

Update finds rows by a key column and updates the rest.

  1. Set Operation to Update
  2. Set Table and the Update Key (the column used in the WHERE clause, e.g., id)
  3. Map the columns to update

The Update Key value comes from {{ $json.id }} — n8n constructs UPDATE table SET col=val WHERE key_col=key_val for you.


Common Patterns

Webhook → INSERT → respond

Receive a form or API payload, insert it into MySQL, return a confirmation.

  1. Webhook node receives the POST
  2. MySQL node inserts the data (INSERT INTO leads (email, name) VALUES (?, ?))
  3. Respond to Webhook returns { "success": true, "id": "{{ $json.insertId }}" }

Daily report: SELECT → Google Sheets

  1. Cron trigger fires daily
  2. MySQL runs SELECT * FROM orders WHERE DATE(created_at) = CURDATE()
  3. Google Sheets node appends the rows to a daily log sheet

External API → MySQL upsert

  1. HTTP Request fetches records from an external API
  2. MySQL executes an INSERT ... ON DUPLICATE KEY UPDATE:
INSERT INTO products (sku, name, price) VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE name=VALUES(name), price=VALUES(price)
Enter fullscreen mode Exit fullscreen mode

Gotchas Table

Symptom Root cause Fix
ECONNREFUSED Host unreachable or wrong port Check host, port 3306, firewall/security group rules
ER_ACCESS_DENIED_ERROR Wrong user/password or insufficient privileges Grant SELECT, INSERT, UPDATE, DELETE on the specific database
SSL connection error Cloud DB requires SSL, toggle is off Enable SSL in credentials; set Verify server certificate appropriately
ER_PARSE_ERROR SQL syntax error Test query in a MySQL client first; backtick reserved-word column names
affectedRows: 0 on UPDATE WHERE clause matched nothing Log the key value before the query; verify the record exists
Timeout on large SELECTs Returning too many rows Add LIMIT; paginate with OFFSET; or use Split In Batches
insertId: 0 on INSERT Table has no AUTO_INCREMENT primary key Expected — insertId is only set when an auto-increment column exists

Free Workflow JSON — Webhook → MySQL Lead Capture

This workflow receives a form submission via webhook, inserts the lead into a MySQL table, and responds with the new record ID.

Required table:

CREATE TABLE leads (
  id INT AUTO_INCREMENT PRIMARY KEY,
  email VARCHAR(255) NOT NULL,
  name VARCHAR(255),
  source VARCHAR(100),
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Enter fullscreen mode Exit fullscreen mode

Drop a comment below and I'll share the full workflow JSON — just tell me which MySQL provider you're using (PlanetScale, Railway, RDS, or self-hosted) and I'll include the right SSL config.


Workflow Starter Pack ($29)

If you want pre-built, production-ready workflows with error handling, retry logic, and Slack alerting built in, the n8n Workflow Starter Pack includes a complete MySQL lead capture and sync workflow alongside 2 other production workflows.

Every workflow is documented, tested, and imports in under 2 minutes.


What do you use MySQL for in your n8n workflows? SELECT queries for reporting, writes from webhooks, or keeping a database in sync with an external API? Let me know in the comments.

Top comments (1)

Collapse
 
pirateprentice profile image
Pirate Prentice

Quick setup tip for MySQL connections in n8n 🛢️

If you're getting "Connection refused" on port 3306, the most common culprit is the MySQL user not being granted remote access. Run this in your MySQL shell:

GRANT ALL PRIVILEGES ON yourdb.* TO 'n8nuser'@'%' IDENTIFIED BY 'password';
FLUSH PRIVILEGES;
Enter fullscreen mode Exit fullscreen mode

Also: if you're running n8n in Docker and MySQL on the host, use host.docker.internal instead of localhost — caught me out the first time.

Which MySQL operation do you use most in your n8n workflows — reads, writes, or upserts?****