From Spreadsheet to Database: A CSV Migration Checklist
Every production database starts somewhere. For many teams, that somewhere is a spreadsheet. Whether it's a Google Sheet tracking customers, an Excel file with inventory data, or a Notion table that finally outgrew itself โ the day comes when rows freeze, formulas break, and someone asks, "Can we just put this in Postgres?"
CSV is the universal bridge between spreadsheets and SQL. But dumping a CSV into a database without a plan is how you end up with VARCHAR(255) columns that should be DATE, duplicate primary keys, and silent data truncation. This checklist will help you migrate cleanly.
Phase 1: Audit Your Data (Before You Touch SQL)
Phase 2: Design Your Schema
CSV files are flat. Relational databases are not. Before you create a single table, ask whether your data should be normalized.
When to keep it flat (one table)
- Under 10,000 rows
- No repeating groups or multi-value cells
- No obvious parent-child relationships
- You need the migration done in the next hour
When to normalize (multiple tables)
- Cells contain comma-separated values (e.g.,
tags: "red, blue, green") - The same entity appears in multiple rows with redundant data
- You have lookup values that should be foreign keys (e.g.,
statuscolumn with 5 repeated strings) - You plan to query with JOINs in the future
Phase 3: Generate and Validate SQL
Once your CSV is clean and your schema is sketched, it's time to generate the actual SQL. You have two options: manual DDL or a tool.
Manual DDL gives you full control but is error-prone. A tool like SchemaLens CSV to SQL Converter auto-detects delimiters, infers column types, and generates dialect-correct CREATE TABLE and INSERT statements for PostgreSQL, MySQL, SQLite, and SQL Server.
Phase 4: Migrate the Data
With a validated schema, you're ready for the full migration. The exact method depends on your database size and tooling.
Small datasets (< 10,000 rows)
Use multi-row INSERT statements generated by a converter tool. Batch them in groups of 500โ1,000 to avoid statement size limits.
Medium datasets (10,000 โ 1,000,000 rows)
Use your database's native bulk import command:
-- PostgreSQL
COPY users FROM '/path/to/users.csv' WITH (FORMAT csv, HEADER true);
-- MySQL
LOAD DATA INFILE '/path/to/users.csv'
INTO TABLE users
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;
-- SQLite
.mode csv
.import /path/to/users.csv users
Large datasets (> 1,000,000 rows)
Use a dedicated ETL tool like pgloader (PostgreSQL), mysqlimport, or a streaming pipeline. For one-time migrations, pgloader handles type casting, encoding conversion, and batching automatically.
Phase 5: Validate Everything
Importing is not the end. Validation is. Run these checks before you declare victory:
Phase 6: Post-Migration Cleanup
Convert CSV to SQL in seconds
Paste your CSV data and get CREATE TABLE + INSERT statements for PostgreSQL, MySQL, SQLite, or SQL Server. Auto-detects types and delimiters.
Open CSV to SQL ConverterCommon Pitfalls to Avoid
Assuming CSV is UTF-8. Excel on macOS exports UTF-8. Excel on Windows often exports Windows-1252. Always verify encoding before importing.
Ignoring leading zeros. ZIP codes, phone numbers, and IDs that start with zeros will lose those zeros if imported as integers. Store them as TEXT or VARCHAR.
Using spreadsheet formulas as data. If a cell contains =A1+B1, the CSV export will contain the calculated value โ which is what you want. But verify that calculated values were actually exported and not the formula string.
Forgetting time zones. Spreadsheets don't store time zones. If your timestamps need zone awareness, decide on a canonical zone (usually UTC) and convert before import.