DEV Community

hammadrasool2000-svg
hammadrasool2000-svg

Posted on AI-assisted

Convert CSV to SQL INSERT Statements Quickly (Without Breaking Your Data)

Someone sends you a spreadsheet: a customer export, a product list, a CRM dump. You need it in a database table, ideally in the next five minutes. Here's how to go from CSV to SQL INSERT statements quickly, and what to watch for so the import doesn't silently corrupt your data.

The traps (read this first)

Turning CSV into SQL looks like simple string concatenation, and that's exactly how bugs get in:

  1. Commas inside values. "Khan, Sara" is one field, not two. Splitting on , breaks it.
  2. Quotes inside values. O'Brien will end your SQL string early unless the quote is escaped as O''Brien.
  3. Leading zeros. Zip codes and phone numbers like 05400 or 03001234567 become 5400 if you treat them as integers.
  4. Empty cells. Should they be '' or NULL? Usually NULL.
  5. Booleans and dates. true / 1 / TRUE, and dates in YYYY-MM-DD vs 14/03/2026, depend on your database.
  6. Dialect differences. MySQL quotes names with backticks, PostgreSQL and SQLite use double quotes, SQL Server uses brackets, and SQL Server caps a single INSERT ... VALUES at 1,000 rows.

Keep these in mind whichever method you use.

Option 1: Paste it into a converter (fastest)

For a one-off import, a browser converter is the quickest route. The CSV to SQL converter on ToolStash takes pasted CSV or a .csv file and produces CREATE TABLE plus INSERT statements for MySQL/MariaDB, PostgreSQL, SQL Server, SQLite or Oracle. It handles the traps above for you:

  • Standard CSV quoting, so commas, line breaks and doubled quotes inside quoted fields work.
  • Single quotes are escaped, and empty cells become NULL.
  • Column types are guessed from the data (INT, DECIMAL, BOOLEAN, DATE), but values with leading zeros stay as text.
  • Multi-row INSERTs for faster imports, respecting the SQL Server row limit.
  • Delimiters (comma, semicolon, tab, pipe) are detected automatically.

It runs in the browser, so the data doesn't leave your machine. Example input:

id,name,email,signup_date,active
1,"Khan, Sara",sara@example.com,2026-03-14,true
2,Ali Raza,ali@example.com,2026-04-02,false
Enter fullscreen mode Exit fullscreen mode

Output for MySQL with the table name customers:

CREATE TABLE `customers` (
  `id` INT,
  `name` VARCHAR(255),
  `email` VARCHAR(255),
  `signup_date` DATE,
  `active` BOOLEAN
);

INSERT INTO `customers` (`id`, `name`, `email`, `signup_date`, `active`) VALUES
(1, 'Khan, Sara', 'sara@example.com', '2026-03-14', TRUE),
(2, 'Ali Raza', 'ali@example.com', '2026-04-02', FALSE);
Enter fullscreen mode Exit fullscreen mode

Always review the generated CREATE TABLE before running it. Inferred types are a starting point. You'll often want a primary key, a NOT NULL or two, or a longer VARCHAR.

Option 2: A small Python script (repeatable)

If you do this regularly, script it. Python's csv module handles the quoting rules correctly:

import csv
import sys

def sql_value(v):
    if v == "":
        return "NULL"
    # keep leading-zero values (zip codes, phones) as text
    if v.lstrip("-").isdigit() and not (len(v) > 1 and v.lstrip("-").startswith("0")):
        return v
    return "'" + v.replace("'", "''") + "'"

def csv_to_inserts(path, table, batch=500):
    with open(path, newline="", encoding="utf-8") as f:
        reader = csv.reader(f)
        header = next(reader)
        cols = ", ".join(f'"{c}"' for c in header)
        rows = [f"({', '.join(sql_value(v) for v in r)})" for r in reader]

    for i in range(0, len(rows), batch):
        chunk = ",\n".join(rows[i:i + batch])
        print(f'INSERT INTO "{table}" ({cols}) VALUES\n{chunk};\n')

csv_to_inserts(sys.argv[1], sys.argv[2])
Enter fullscreen mode Exit fullscreen mode

Run it:

python csv_to_sql.py customers.csv customers > customers.sql
psql mydb -f customers.sql
Enter fullscreen mode Exit fullscreen mode

This version uses double-quoted identifiers (PostgreSQL/SQLite style). Swap in backticks for MySQL. Batching keeps each statement a reasonable size.

Option 3: Skip INSERTs entirely for big files

For hundreds of thousands of rows, generated INSERT statements are the slow way. Every database has a native bulk loader:

-- PostgreSQL (from psql)
\copy customers FROM 'customers.csv' WITH (FORMAT csv, HEADER true);

-- MySQL
LOAD DATA LOCAL INFILE 'customers.csv'
INTO TABLE customers
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 LINES;

-- SQL Server
BULK INSERT customers FROM 'C:\data\customers.csv'
WITH (FORMAT = 'CSV', FIRSTROW = 2);
Enter fullscreen mode Exit fullscreen mode

These still need the table to exist. A handy workflow is to generate just the CREATE TABLE with a converter, adjust it, then bulk-load the file. ToolStash has a longer guide to importing CSV with LOAD DATA, \copy and BULK INSERT if you need the details for each database.

When to use what

Situation Best approach
One-off, a few thousand rows Paste into a converter, review, run
Recurring import, same format Python (or your language) script
Very large file Native bulk loader (\copy, LOAD DATA, BULK INSERT)
Excel file Save as CSV first, then any of the above

Final checks before you hit Run

  • Open the CSV in a text editor (not Excel) to check the delimiter and encoding. UTF-8 avoids broken characters.
  • Confirm the header row is present, or name the columns yourself.
  • Spot-check rows with commas, quotes and empty cells in the output.
  • Run it inside a transaction (BEGIN; ... ROLLBACK;) first if you're importing into a shared database.

With quoting, NULLs and leading zeros handled properly, a CSV-to-SQL import is a five-minute job.

Top comments (0)