How to use
- Paste CSV, drop a
.csvfile on the box, or press Load sample. - Pick your database under Dialect and type the Table name.
- Choose Rows per INSERT, and untick Add CREATE TABLE if the table already exists.
- Read any notes under the result: renamed columns, dropped extra values, a split for SQL Server.
- Copy to clipboard or Download .sql, or open the result in the SQL Formatter with Format this SQL.
What it writes, and why the escaping differs per database
Joining CSV values into INSERT statements by hand fails on the first name with an apostrophe in it. The fix is not the same everywhere: every database doubles a single quote (O''Brien), but MySQL also reads backslashes as escapes, and SQL Server needs an N before a string that holds characters outside its code page, or they are stored as question marks. This tool applies the rules of the database you pick under Dialect, and the site's tests read every generated string back through that dialect's quoting rules, and run the SQLite output in a real SQLite database, to check that each value arrives unchanged.
With Add CREATE TABLE on, each column gets the narrowest type that fits every value in it: whole numbers become INTEGER or BIGINT, decimals get a DECIMAL with exactly the precision and scale the data needs, true/false becomes a boolean, and real calendar dates become DATE or a timestamp type. Anything else, including a single value that does not fit, makes the column text, sized to its longest value.
It does not guess a primary key, NOT NULL or indexes, because a CSV cannot tell it which column is unique or required; add those to the CREATE TABLE yourself. It never connects to a database or runs anything.
Example
The file that Load sample inserts, with an apostrophe, a comma inside a quoted field, an accented name, a ZIP code with a leading zero and two empty cells:
id,name,city,zip,signup_date,active,balance
1,Ada Lovelace,London,01234,2026-01-15,true,1250.50
2,Seán O'Brien,"Dublin, Ireland",,2026-02-03,false,0
3,Grace Hopper,New York,10001,2026-03-21,true,becomes, with the default options (Standard SQL, 100 rows per INSERT):
CREATE TABLE my_table (
id INTEGER,
name VARCHAR(12),
city VARCHAR(15),
zip VARCHAR(5),
signup_date DATE,
active BOOLEAN,
balance DECIMAL(6, 2)
);
INSERT INTO my_table (id, name, city, zip, signup_date, active, balance) VALUES
(1, 'Ada Lovelace', 'London', '01234', '2026-01-15', TRUE, 1250.50),
(2, 'Seán O''Brien', 'Dublin, Ireland', NULL, '2026-02-03', FALSE, 0),
(3, 'Grace Hopper', 'New York', '10001', '2026-03-21', TRUE, NULL);With SQL Server the second row is (2, N'Seán O''Brien', N'Dublin, Ireland', NULL, '2026-02-03', 0, 0),: text gets the N prefix and the boolean becomes 0, stored in a BIT column. With SQLite, which has no DATE or BOOLEAN type, the columns are id INTEGER, name TEXT, city TEXT, zip TEXT, signup_date TEXT, active INTEGER, balance NUMERIC.
Options explained
- Dialect: Standard SQL, MySQL / MariaDB, PostgreSQL, SQL Server (T-SQL) or SQLite. It sets how names and strings are quoted, how booleans are written (TRUE/FALSE, or 1/0 in SQL Server and SQLite) and which type names the CREATE TABLE uses.
- Table name: used in every statement and as the download's file name.
schema.tableis split on the dot, and a name you type in quotes is kept as typed. - Rows per INSERT: 1 / 100 / 500 / 1,000 / All rows in one INSERT. Fewer rows per statement means a failing row takes fewer others down with it; more rows means a shorter script. SQL Server is capped at 1,000.
- Add CREATE TABLE: untick it when the table already exists and you only need the rows.
- Detect numbers, booleans and dates: untick it to make every column text and quote every value, which is the safe choice when you will convert types in SQL afterwards.
- Empty text cells: NULL / Empty text ('') sets what an empty cell becomes in a text column. In a number, date or boolean column an empty cell is always NULL, because
''is not a valid number or date. - Field separator: Comma / Semicolon / Tab. Semicolon is what Excel writes in countries that use a comma as the decimal mark; tab is a TSV file.
- First row is column names: untick it for a file with no header, and the columns become
column_1,column_2and so on. - Column names in snake_case rewrites headers into names that never need quotes:
First Namebecomesfirst_name. Without it, a name with a space is quoted as`First Name`in MySQL,"First Name"in PostgreSQL and[First Name]in SQL Server.
Edge cases and common errors
- Long IDs keep every digit. Values are copied into the SQL as written rather than converted to JavaScript numbers, so
9007199254740993(past 253, where most JSON tools round) is inserted as(9007199254740993);. - Impossible dates are text.
2026-02-30looks like a date but is not one, so its column stays text instead of producing an INSERT the database would reject. - Empty cells in typed columns stay NULL even with Empty text ('') selected: an empty name and an empty quantity become
('', NULL). - Rows with too many values keep only as many values as there are columns, and a note says so: "Row 2 has more values than there are columns; the extra values are left out." Rows with too few values get NULL for the missing ones.
- Duplicate or missing column names would make the CREATE TABLE fail, so they are renamed and reported: "Two columns are called Email; the later one is called Email_2."
- More than 1,000 rows for SQL Server in one INSERT raise error 10738 there, so the tool splits them: "SQL Server accepts at most 1,000 rows in one INSERT, so the rows are split into statements of 1,000."
- Names that are SQL keywords, such as a column called
orderoruser, are quoted automatically. PostgreSQL also folds unquoted names to lower case, so a header likeCustomerIdbecomes the columncustomeridthere; tick Column names in snake_case if you want predictable names. - Files saved by Excel often start with an invisible byte order mark. It is removed, so it never ends up inside the first column's name.
- Commas, quotes and line breaks inside a field follow the CSV quoting rules the CSV to JSON Converter uses:
"Dublin, Ireland"is one value, not two.
Do the same thing in code
import sqlite3
import pandas as pd
df = pd.read_csv("data.csv", dtype=str)
df.to_sql("my_table", sqlite3.connect("data.db"), index=False)\copy my_table FROM 'data.csv' WITH (FORMAT csv, HEADER true)In a program, send the values as query parameters rather than building INSERT text, which is what pandas does above; dtype=str stops it from reading 01234 as the number 1234. The second line is PostgreSQL's psql client loading a file into an existing table. Before loading, Remove Duplicate Lines can drop repeated rows that would break a primary key, and the SQL Formatter lays out the generated script if you want to read it before running it.