Skip to content

Guide

MySQL: email query results as CSV on a schedule

MySQL / event scheduler / INTO OUTFILE / scheduled SQL exports / email

The MySQL Event Scheduler cannot email and INTO OUTFILE is blocked by secure_file_priv and on RDS. Working ways to send query results as CSV.

Every MySQL database used by a business eventually gets the same request: a list, every morning, in Excel. The first instinct is to look inside MySQL for a scheduler and an export command, and both exist. Neither of them gets a file into somebody's inbox.

What MySQL can do on its own

The Event Scheduler runs SQL on a timetable once event_scheduler is ON:

CREATE EVENT daily_open_orders
ON SCHEDULE EVERY 1 DAY STARTS '2026-10-18 07:00:00'
DO
  INSERT INTO report_open_orders
  SELECT order_id, customer_name, total, NOW()
  FROM orders WHERE status = 'open';

It is good for filling a reporting table. It runs statements inside the server and has no way to send mail.

SELECT ... INTO OUTFILE writes a result to a file:

SELECT order_id, customer_name, total, created_at
FROM orders WHERE status = 'open'
INTO OUTFILE '/var/lib/mysql-files/open_orders.csv'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n';

It writes on the database server, only inside the directory allowed by secure_file_priv, only with the FILE privilege, and it fails if the file already exists, so a scheduled run needs a different file name every time. It does not write a header row, which leads to the familiar UNION ALL of column names on top of the query. On Amazon RDS and Aurora MySQL it is not available, because there is no server filesystem to write to.

The client side approach that actually ships

Most working setups run the query from another machine with the mysql client and post-process the output:

mysql --defaults-extra-file=/etc/reports/sales.cnf --batch \
  -e "SELECT order_id, customer_name, total, created_at FROM orders WHERE status = 'open'" sales \
  > /srv/exports/open_orders.tsv

--batch produces tab-separated output with a header. Converting it to CSV with sed works until a value contains a comma or a quote, so many teams simply send the TSV, which Excel opens without complaint. MySQL Shell is the cleaner tool when it is available: util.exportTable writes a proper CSV with a dialect option, although it exports a table rather than an arbitrary query, so the query usually goes into a view first.

Then cron schedules the script and a mail client sends it, exactly as on any Linux host. The defaults file keeps the password out of the command line and the process list.

The parts that age badly

The result is a small system made of an event or a cron entry, a script, a credentials file, a mail relay and a folder of exports. It is invisible to the people who asked for the report, and when the column list changes somebody has to remember which server the script lives on. On managed MySQL the server-side half of the toolkit disappears, so whatever was built around INTO OUTFILE has to be rebuilt on the client side anyway.

Doing it with Taavik

Taavik's scheduled SQL exports run the query through an agent inside the network, which reaches MySQL like any client and only makes outbound connections to the workspace. That makes self-hosted MySQL, RDS and Aurora the same case. The query is saved in a shared library with {{variables}}, a schedule turns it into a correctly quoted CSV with a header or an Excel file, and delivery goes to an email list or a Slack channel, with the option to send only when the query returned rows.

Nothing is written on the database server, and there is no FILE privilege to grant. The agent needs a read-only login, and the password is encrypted in the browser for that agent before it is stored.

Recipients receive a link to the file rather than an attachment, because the export is encrypted before it leaves the network and opens with a passphrase. Every run is recorded with its status and row count. The free plan covers one connection and one daily schedule, which is enough to replace the first cron job and see whether the rest are worth moving.