Home CSV to SQL

CSV to SQL converter

Turn a CSV file into a CREATE TABLE and a batched INSERT, with column types read from the data rather than guessed as TEXT. Runs in this tab; nothing is uploaded.

How column types are inferred

A converter that emits forty columns of TEXT has not saved you any work. This one reads every value in a column and picks the narrowest type that fits all of them. Nulls and empty cells are ignored when deciding, so one blank row does not push a numeric column back to text.

When every value is…Column type
true / falseBOOLEAN
a whole number, at most 15 digitsBIGINT
numeric with a decimal pointDECIMAL(18,6)
YYYY-MM-DDDATE
YYYY-MM-DD followed by a timeTIMESTAMP
a UUIDUUID
text, longest value ≤ 255VARCHAR(n)
text, longest value > 255TEXT
all emptyTEXT

Why VARCHAR widths are rounded up

A column whose longest value is 41 characters does not become VARCHAR(41). It becomes VARCHAR(64): the width is the longest value plus half again, rounded up to a multiple of 16 and capped at 255. Sizing a column to the sample is the mistake that makes the schema work perfectly on the file you converted and reject the next one — the sample tells you the order of magnitude, not the limit.

Quoting and injection

Identifiers are quoted for the dialect you pick — "double quotes" for PostgreSQL, `backticks` for MySQL — so a column called order or group does not collide with a keyword. Single quotes inside values are doubled, which is the escaping that matters here: the output of this page is, by definition, text someone is about to paste into a database console.

What it produces

One CREATE TABLE followed by a single multi-row INSERT. A batched insert is dramatically faster than one statement per row — on most engines the difference is an order of magnitude on a few thousand rows, because it is one parse and one transaction rather than thousands.

Empty cells become NULL, not ''. If your loader needs the opposite, turn type detection off and the empty strings come through literally.

Before you run it

  • There is no primary key. Nothing in a CSV file says which column is one. Add the constraint yourself, or add an identity column.
  • There are no indexes. Add them after the insert, not before — building an index while loading is slower than building it once at the end.
  • Dates are not validated. A column that looks like a date is typed as one; a row with 2024-02-31 in it will be rejected by the database, which is the right place for that to fail.
  • Very large files belong in a bulk loader. Past a few thousand rows, COPY or LOAD DATA will beat any INSERT.

Common questions

Which SQL dialects are supported?

PostgreSQL and MySQL. The difference is identifier quoting — double quotes versus backticks — and both outputs are close enough to standard SQL to run on SQLite and SQL Server with small edits.

Does it create a primary key?

No. Nothing in a CSV file identifies which column is the key, so guessing would be wrong as often as it was right. Add the constraint after the CREATE TABLE, or add an identity column.

How are column types chosen?

By reading every value in the column and picking the narrowest type all of them fit — boolean, bigint, decimal, date, timestamp, uuid, varchar or text. Empty cells are ignored when deciding, so one blank row does not force a numeric column to text.

Are values escaped safely?

Single quotes inside values are doubled, which is the SQL string escape. Identifiers are quoted for the dialect, so a column named order or group does not collide with a keyword.

Is the file uploaded to a server?

No. Everything runs in your browser, which matters more here than usual — the CSV files people convert to SQL tend to be the ones they cannot paste into a hosted tool.

Last updated