Skip to content

MySQL - Export Table into CSV File

Exporting data to a Comma-Separated Values (CSV) file is a common requirement for data analysis, reporting, backups, or migrating data to other systems. MySQL provides several methods to accomplish this, each with its own use cases and security considerations.

This tutorial covers two primary approaches: the server-side SELECT ... INTO OUTFILE command and the more flexible client-side scripting method.

Method 1: Server-Side Export with SELECT ... INTO OUTFILE

Section titled “Method 1: Server-Side Export with SELECT ... INTO OUTFILE”

This SQL command instructs the MySQL server to write the results of a SELECT query directly to a file on the server’s filesystem. It is extremely fast but comes with significant security restrictions.

Critical Security Prerequisite: secure_file_priv

Section titled “Critical Security Prerequisite: secure_file_priv”

For security reasons, SELECT ... INTO OUTFILE can only write to a specific directory configured by the secure_file_priv system variable. You must check its value before attempting an export:

SHOW VARIABLES LIKE 'secure_file_priv';

The result will be one of the following:

  • A specific path (e.g., /var/lib/mysql-files/): This is the most common and secure configuration. You can only write files to this directory.
  • An empty string: This is a security risk. It means MySQL can write files anywhere on the server’s filesystem that the MySQL process user has permissions for. This configuration is strongly discouraged.
  • NULL: This means file import/export operations are disabled. You cannot use SELECT ... INTO OUTFILE.

On many managed cloud database services like AWS RDS or Google Cloud SQL, secure_file_priv is set to NULL by default, making this method unusable. In such cases, you must use a client-side method.

SELECT column1, column2, ... FROM your_table
INTO OUTFILE '/path/to/your/secure/directory/filename.csv'
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n';

Let’s assume secure_file_priv is set to C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/. We’ll use the following customers table:

CREATE TABLE customers(
ID INT NOT NULL PRIMARY KEY,
NAME VARCHAR(20) NOT NULL,
AGE INT NULL,
ADDRESS CHAR(25),
SALARY DECIMAL(18, 2)
);
INSERT INTO customers VALUES
(1, 'Ramesh', 32, 'Ahmedabad', 2000.00),
(2, 'Khilan', 25, 'Delhi', 1500.00),
(3, 'Kaushik', 23, NULL, 2000.00);

The following query exports the data:

SELECT * FROM customers
INTO OUTFILE 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/customers_export.csv'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n';

Error Handling: The command will fail if the target file already exists. This is a safety feature to prevent accidental overwrites. You must delete the file from the server’s filesystem before re-running the command.

Advanced Technique: Exporting with Headers

Section titled “Advanced Technique: Exporting with Headers”

INTO OUTFILE doesn’t natively support column headers. A common workaround is to use UNION ALL to create a header row:

(SELECT 'ID', 'NAME', 'AGE', 'ADDRESS', 'SALARY')
UNION ALL
(SELECT ID, NAME, AGE, ADDRESS, SALARY FROM customers)
INTO OUTFILE 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/customers_with_headers.csv'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n';
Section titled “Method 2: Client-Side Scripting (Recommended & More Flexible)”

A more modern and portable approach is to write a script in a language like Python or Node.js. This script connects to the database, fetches the data, and then writes it to a local CSV file. This method works everywhere, including on cloud databases, and gives you full control over the output format.

Python Example (using csv and mysql-connector-python)

Section titled “Python Example (using csv and mysql-connector-python)”

This approach is robust, secure, and the industry standard for application-driven data exports.

import mysql.connector
import csv
DB_CONFIG = {
'user': 'root',
'password': 'your_password',
'host': '127.0.0.1',
'database': 'your_database'
}
OUTPUT_FILE = 'customers_export_from_python.csv'
def export_customers_to_csv():
try:
with mysql.connector.connect(**DB_CONFIG) as conn:
with conn.cursor(dictionary=True) as cursor:
cursor.execute("SELECT ID, NAME, AGE, ADDRESS, SALARY FROM customers;")
rows = cursor.fetchall()
if not rows:
print("No data to export.")
return
# Get headers from the keys of the first dictionary in the list
headers = rows[0].keys()
with open(OUTPUT_FILE, 'w', newline='', encoding='utf-8') as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=headers)
writer.writeheader()
writer.writerows(rows)
print(f"Data successfully exported to {OUTPUT_FILE}")
except mysql.connector.Error as err:
print(f"Database Error: {err}")
except IOError as e:
print(f"File Error: {e}")
export_customers_to_csv()

Node.js Example (using mysql2 and fast-csv)

Section titled “Node.js Example (using mysql2 and fast-csv)”

For Node.js, libraries like fast-csv make streaming large datasets efficient.

// First, install dependencies: npm install mysql2 fast-csv
const mysql = require('mysql2');
const fs = require('fs');
const { format, writeToStream } = require('@fast-csv/format');
const dbConfig = {
host: 'localhost',
user: 'root',
password: 'your_password',
database: 'your_database'
};
async function exportCustomers() {
const connection = mysql.createConnection(dbConfig);
const outputPath = 'customers_export_from_node.csv';
const writeStream = fs.createWriteStream(outputPath);
try {
console.log('Connecting to database...');
const queryStream = connection.query('SELECT * FROM customers').stream();
const csvStream = format({ headers: true });
console.log(`Streaming data to ${outputPath}...`);
queryStream.pipe(csvStream).pipe(writeStream);
return new Promise((resolve, reject) => {
writeStream.on('finish', () => {
console.log('Export completed successfully.');
resolve();
});
writeStream.on('error', reject);
queryStream.on('error', reject);
});
} catch (error) {
console.error('An error occurred:', error);
} finally {
connection.end();
}
}
exportCustomers();
CriteriaSELECT ... INTO OUTFILEClient-Side Scripting
SpeedVery Fast (server-side operation)Slower (data travels over the network)
FlexibilityLow (limited formatting, fixed path)High (full control over format, logic, and output location)
SecurityHigh Risk if misconfiguredSecure (standard application database access)
PortabilityLow (fails on many cloud platforms)High (works anywhere your app can connect to the DB)
Best ForQuick, one-off exports by a DB administrator with server access.Automated reports, application features, and exporting from restricted/cloud environments.