Skip to main content

Connect to MySQL

Create a MySQL resource to connect Retool to MySQL databases. MySQL is an open-source relational database management system. MySQL resources enable you to securely connect to your databases and build admin panels, reporting dashboards, and data management tools.

What you can do with MySQL

  • Query data: Retrieve data using SQL mode for custom SQL queries with support for complex JOINs, subqueries, and aggregations.
  • Manage data: Insert, update, and delete records using GUI mode for write operations.
  • Execute transactions: Perform multi-statement transactions with automatic rollback on errors.
  • Call procedures: Execute MySQL stored procedures and functions with parameters and return values.
  • Work with data types: Query and manipulate JSON columns, spatial data types, and other MySQL-specific types.

Before you begin

To connect MySQL to Retool, you need the following:

  • Database credentials: Username and password with appropriate permissions, or AWS IAM credentials for RDS instances.
  • Network access: Database must accept connections from Retool's IP addresses. For databases not publicly accessible, configure an SSH tunnel.
  • Retool permissions: Edit all permissions for resources in your organization.

Create a MySQL resource

Follow these steps to create a MySQL resource in Retool.

1. Create a new resource

In your Retool organization, navigate to Resources in the main navigation and click Create newResource. Search for MySQL and click the MySQL tile to begin configuration.

Searching for MySQL in the resource creation page.

Use folders to organize your resources by team, environment, or data source type. This helps keep your resource list manageable as your organization grows.

2. Configure connection settings

Configure the following connection settings for your MySQL resource.

MySQL connection settings form.

Resource name and description

Specify a name for the resource that indicates which database it connects to. Include a description that can provide more context to users and Assist about how to use the resource.

Example NameExample Description
Customer database (readonly)A read-only MySQL database that contains customer and order information.
Analytics databaseA read/write MySQL database with product analytics and usage metrics.

Host

The hostname or IP address of your MySQL server.

Examples
mydb.abc123.us-east-1.rds.amazonaws.com
mysql-instance.c.my-project.internal
mysql.example.com
192.168.1.100

Port

The port number for your MySQL server. Default is 3306.

Database name

The name of the database to connect to on the MySQL server. Leave blank to connect to the default database.

Connection options

Additional connection parameters for MySQL. Add custom connection options as query parameters.

Examples
// Set timezone
timezone=UTC

// Connection timeout
connectTimeout=10000

// Enable multiple statements
multipleStatements=true

// Set SQL mode
sqlMode=TRADITIONAL

SSH tunnel

If your MySQL server is not publicly accessible, configure an SSH tunnel to connect through a bastion host. Provide SSH host, port, username, and authentication method (password or private key).

Outbound region

Select the outbound region from which Retool connects to your database. Choose a region geographically close to your database for optimal performance. Retool routes traffic through the selected region's IP addresses.

3. Configure authentication

MySQL supports multiple authentication methods based on your deployment type and security requirements.

Authentication methodUse cases
Username and passwordStandard authentication for most MySQL deployments. Simple to set up and widely supported. Use configuration variables or to store credentials securely.
AWS IAM authenticationRecommended for Amazon RDS or Aurora MySQL instances. Eliminates the need to manage database passwords. Provides fine-grained access control through IAM policies. Automatically rotates credentials.
Connection stringConvenient when you have a pre-formatted connection string with all parameters. Useful for quick testing or when migrating from other tools. Can include authentication and connection settings in a single field.

Select an authentication method from the Authentication dropdown and provide the required credentials. For sensitive values like passwords and access keys, use configuration variables or rather than hardcoding them.

MySQL authentication settings with username and password.

4. Configure SSL/TLS

Configuring SSL/TLS is optional but highly recommended. Enable SSL/TLS for encrypted connections to your MySQL server.

FieldDescription
SSL/TLSEnable SSL/TLS encryption for the connection.
Reject unauthorizedReject connections if the server's SSL certificate cannot be verified. Enabled by default for security.
CA certificateProvide your certificate authority (CA) certificate for SSL verification.
Client certificate and keyFor mutual TLS authentication, provide client certificate and private key.

For cloud databases like AWS RDS or Google Cloud SQL, SSL certificates may be required. Download the appropriate CA certificate from your cloud provider's documentation.

5. Test the connection

Click Test connection to verify Retool can connect to your MySQL database. A successful test confirms the hostname, port, credentials, and network access are configured correctly.

If the connection test fails, verify:

  • Database server is running and accessible from Retool
  • Hostname and port are correct
  • Authentication credentials are valid
  • Firewall rules allow connections from Retool's IP addresses
  • SSL/TLS settings match your database configuration

6. Save the resource

Click Create resource to save your MySQL resource. The resource is now available to use in apps, workflows, and agent tools across your Retool organization.

Query MySQL data

Once you've created a MySQL resource, you can query it in apps, workflows, and agent tools.

Create a query

You can create a MySQL query in a Retool app using Assist to generate queries with natural language, or manually using code.

Use Assist to generate queries from natural language prompts. Assist can create queries to retrieve, filter, and manipulate data from your MySQL resource.

To create a query with Assist:

  1. In the Retool app IDE, click the Assist button at the bottom of the left toolbar to open the Assist panel (if not already visible).
  2. Write a prompt describing the data you want to retrieve, referencing your resource using @.
  3. Press Enter to submit the prompt.
  4. Select your MySQL resource when prompted.
  5. Review the generated query and click Run query to add it to your app.
Example prompt
retrieve 25 rows from products table using @MySQL

Action types

MySQL queries support two modes: SQL mode for reading data with custom SQL queries and GUI mode for write operations. In GUI mode, you can select from multiple action types for different write operations.

Action typeDescriptionUse case
Insert a recordAdd a single new row to a table.Create records from form submissions.
Update an existing recordModify an existing row identified by primary key or filter.Edit individual records with inline editing.
Update a record, or create a new record if it doesn't existUpdate an existing record or create a new one if the record doesn't exist.Upsert operations based on filter criteria.
Delete a recordRemove rows based on filter criteria.Delete records with confirmation.
Bulk insert recordsAdd multiple new rows to a table in a single operation.Bulk create records from imported data.
Bulk update via a primary keyUpdate multiple records identified by primary key.Batch update operations.
Bulk upsert via a primary keyInsert or update multiple rows based on a primary key.Import data that may contain new or existing records.

Query configuration fields

Configuration fields vary based on the mode and action type you select. Field values can be static (e.g., user_123) or dynamic by using an embedded expression (e.g., {{ userSelect1.value }}).

SQL mode

For reading data with custom SQL queries.

SQL query

The SQL statement to execute.

Example query
SELECT id, name, email, status, created_at
FROM users
WHERE status = 'active'
AND created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)
ORDER BY created_at DESC
LIMIT 100

Use embedded expressions to make queries dynamic:

Example with embedded expressions
SELECT id, name, email, role
FROM users
WHERE email LIKE {{ '%' + searchInput.value + '%' }}
AND role = {{ roleSelect.value }}
ORDER BY created_at DESC
LIMIT {{ table1.pagination.pageSize }}
OFFSET {{ table1.pagination.offset }}

GUI mode

For write operations using the graphical interface.

Action type

Select from the action types listed in the Action types table above.

Table name (all action types)

The database table to query.

Examples
// Static table name
users

// Dynamic table name
{{ dropdown1.value }}
Records (Insert multiple records, Bulk upsert by key)

The data to insert or upsert.

Insert from array
{{ table1.data }}
Transform file upload
{{
fileInput1.parsedValue.map((row) => ({
name: row.Name,
email: row.Email,
status: "active",
}))
}}
Construct array manually
[
{
name: form1.data.name,
email: form1.data.email,
role: form1.data.role,
},
]
Filter by (Update an existing record, Update/create if not exists, Delete a record)

The WHERE clause conditions for filtering rows.

Example
{{ { status: "active", role: roleSelect.value } }}
Primary key column (Update a record, Delete a record, Bulk upsert by key)

The column used as the primary key for identifying records.

Example
// Primary key column name
id

// Composite key (for bulk upsert)
["user_id", "product_id"]
Changeset (Update a record, Update multiple records)

The columns to update with new values.

Use changesetObject to capture changes from inline editing in tables:

Changeset from table
{{ table1.changesetObject }}
Changeset from form
{{ form1.data }}
Changeset with specific fields
{{
{
name: nameInput.value,
email: emailInput.value,
updated_at: new Date().toISOString(),
}
}}

Data types and formatting

MySQL queries return and accept specific data types. Understanding these formats ensures correct data handling in your Retool apps.

Request data formats

When sending data to MySQL, use these formats for different value types:

Value typeDescriptionExample
StringsUse single quotes in SQL or embedded expressions.'text value' or {{ textInput.value }}
NumbersProvide numeric values directly. No quotes needed.123 or 45.67
BooleansUse TRUE or FALSE in SQL, or 1/0 in embedded expressions.TRUE or {{ checkbox.value ? 1 : 0 }}
DatesUse ISO 8601 format strings or MySQL date functions.'2025-01-21' or CURDATE()
TimestampsUse ISO 8601 format or MySQL timestamp functions.'2025-01-21 10:30:00' or NOW()
NULL valuesUse NULL keyword in SQL or null in embedded expressions.NULL or {{ textInput.value }}
JSONUse JSON strings or JavaScript objects.'{"key": "value"}' or {{ JSON.stringify(object1.data) }}

Response data formats

MySQL queries return data in these formats:

Data typeJavaScript typeNotes
INT/BIGINTnumberReturns JavaScript numbers.
DECIMALstringReturns as strings to preserve precision. Parse with parseFloat() if needed.
VARCHAR/TEXTstringReturns as JavaScript strings.
BOOLEANnumberReturns 1 or 0. Convert with Boolean(value) if needed.
DATEstringReturns ISO 8601 date string (e.g., 2025-01-21).
DATETIMEstringReturns ISO 8601 datetime string.
JSONobjectAutomatically parsed to JavaScript objects.
NULLnullReturns JavaScript null.

Common use cases

The following examples demonstrate typical MySQL operations in Retool apps.

read and display data in a table

First, create a query named tableQuery and write an SQL statement to retrieve some data.

Example query
SELECT id, name, email, status, created_at
FROM users
WHERE status = 'active'
ORDER BY created_at DESC
LIMIT 100

Next, add a Table component to the app and set its Data property to {{ tableQuery.data }}. The table dynamically updates to reflect the data structure provided by the query.

filter data with user input

First, add input components for users to specify search filters.

  • A Text Input component (searchInput) for search terms.
  • A Select component (statusSelect) for status filtering.
  • A Date Range Picker component (dateRange) for date filtering.

Next, write a query that references the input component values to filter data.

Example query
SELECT id, name, email, status, created_at
FROM users
WHERE
name LIKE {{ '%' + searchInput.value + '%' }}
AND status = {{ statusSelect.value }}
AND created_at BETWEEN {{ dateRange.value.start }} AND {{ dateRange.value.end }}
ORDER BY created_at DESC

Queries that read data automatically run whenever any referenced input values change by default. As you update the input fields, the query retrieves new data based on the new values.

insert new rows from a form

First, add a Form component (form1) with input fields for the data you want to collect (name, email, role).

Next, create a query in GUI mode to insert a new row using the form data:

FieldValue
Action typeInsert a record
Table nameusers
Records{{ { name: form1.data.name, email: form1.data.email, role: form1.data.role, status: 'active' } }}

Then, add an event handler to the form's Submit event that runs the insert query and displays a success notification.

update data with inline editing

First, add a Table component and enable inline editing by setting Enable saving to true.

Next, create an update query in GUI mode that saves changes made in the table:

FieldValue
Action typeUpdate a record
Table nameusers
Primary key columnid
Changeset{{ table1.changesetObject }}

Then, add an event handler to the table's Save changes event that runs the update query and refreshes the data query.

delete rows with confirmation

First, add a Table component that displays your data and a Button component in an action column for deleting rows.

Next, create a delete query in GUI mode:

FieldValue
Action typeDelete a record
Table nameusers
Primary key columnid

Then, add an event handler to the button's Click event:

  1. Action: Show confirmation modal
  2. If confirmed, trigger the delete query
  3. Then refresh the data query
bulk import from CSV

First, add a File Input component (fileInput1) that accepts CSV files with Parse files enabled and File type set to CSV.

Next, create a bulk upsert query:

FieldValue
Action typeBulk upsert by key
Table nameproducts
Primary key columnsku
Records{{ fileInput1.parsedValue.map(row => ({ sku: row.SKU, name: row.Name, price: parseFloat(row.Price) })) }}

Then, add a Button component that triggers the bulk upsert query when clicked and displays a success notification.

Best practices

Follow these best practices to optimize performance, maintain data integrity, and secure your MySQL queries.

Performance

  • Use indexes: Add indexes on columns frequently used in WHERE clauses, JOIN conditions, and ORDER BY statements to speed up queries.
  • Limit result sets: Always use LIMIT to restrict the number of rows returned, especially for large tables displayed in tables or charts.
  • Use prepared statements: Retool automatically uses prepared statements for MySQL queries, which improves performance and prevents SQL injection.
  • Avoid SELECT *: Select only the columns you need rather than using SELECT * to reduce data transfer and improve performance.
  • Use connection pooling: Retool automatically manages connection pooling for MySQL resources. For high-traffic apps, consider increasing pool size in advanced settings.
  • Optimize complex queries: For expensive aggregations or joins that don't change frequently, consider using MySQL query cache or summary tables.

Security

  • Use configuration variables: Store database credentials in configuration variables or rather than hardcoding them in resources or queries.
  • Use resource environments: Organizations on an Enterprise plan can configure multiple resource environments to maintain separate database configurations for production, staging, and development.
  • Apply least privilege: Grant database users only the minimum permissions needed for their operations. Use read-only users for queries that only need to read data.
  • Validate user input: Always validate and sanitize user input before using it in queries, even when using embedded expressions or prepared statements.
  • Enable SSL/TLS: Use SSL/TLS encryption for connections to protect data in transit, especially when connecting to databases over the internet.
  • Use row-level security: For multi-tenant applications, consider implementing application-level row filtering based on user context to restrict data access.
  • Audit database access: Enable MySQL audit logging to track database access and changes for compliance and security monitoring.

Data integrity

  • Use transactions: Wrap related operations in transactions to ensure atomicity. MySQL automatically rolls back the entire transaction if any statement fails.
  • Validate before delete: Always show confirmation dialogs before executing DELETE operations to prevent accidental data loss.
  • Handle errors gracefully: Configure error notifications and fallback behavior for failed queries to improve user experience.
  • Test with environments: Use separate development and staging databases to test queries before deploying to production.