Code Beautifier

CSV to SQL

Turn CSV rows into CREATE TABLE and INSERT statements for PostgreSQL, MySQL, SQL Server, or SQLite, with column types inferred from the data.

Draft saved locally.

Local workspace

Named projects in IndexedDB · Local only — never synced to our servers. Worksp

Open manager

Batch workspace

Format multiple files locally in one run.

Dialect:
Delimiter:
Rows per INSERT:
csv
Formatted Outputsql

Loading a CSV into a database usually means either a fragile import wizard or hand-written INSERT statements. This converter reads the CSV the way a spreadsheet does, including quoted fields that contain commas and line breaks, then infers a type per column and writes both the CREATE TABLE and batched INSERT statements for your dialect. Values that look numeric but aren't, such as zip codes with a leading zero or 20-digit identifiers, stay text, which is the difference between data that imports correctly and data that quietly changes on the way in.

Common errors and fixes

ERROR: column "order" does not exist

A column name is a reserved word. The generated SQL quotes every identifier for the chosen dialect, so run the output for the database you selected rather than mixing dialects.

ERROR: invalid input syntax for type bigint

A value doesn't match the inferred type, usually because the sample rows were all numeric and the real data isn't. Convert the full file so the column widens to text.

Quoted field not terminated

A quoted CSV field is missing its closing quote, or a literal quote inside it wasn't doubled. RFC 4180 requires "" for a quote inside a quoted field.

Data truncated for column at row 1

MySQL is rejecting a value longer than the column allows. Widen the column, or change the generated TEXT type to the size your schema expects.

Options

OptionDescription
DialectSets how identifiers are quoted, which types are used, and how booleans are written.
Table nameName used in the CREATE TABLE and INSERT statements.
Include CREATE TABLETurn off when the table already exists and you only need the inserts.
First row is a headerOff, columns are named column_1, column_2, and every row is treated as data.
DelimiterDetection works for most files; set it explicitly for semicolon CSVs exported by European spreadsheets.
Rows per INSERTMulti-row inserts load far faster than one statement per row, but very large batches can exceed a server's packet limit.

FAQ

How are column types chosen?

Each column gets the narrowest type that fits every value in it: integer, numeric, boolean, date, timestamp, or text. One value that doesn't fit widens the whole column, so a column of numbers with a single "n/a" becomes text rather than failing on import.

Why is my zip code text instead of a number?

Because 02134 stored as a number becomes 2134. Values with a leading zero stay text, as do numbers longer than 15 digits, which would otherwise lose precision. The same protection covers phone numbers and external IDs.

How are apostrophes and quotes escaped?

A single quote is doubled, so O'Brien becomes 'O''Brien'. For MySQL, backslashes are escaped too, because MySQL treats them as escape characters inside string literals by default.

What happens to empty cells?

They become NULL. CSV can't distinguish an empty string from a missing value, so if a column genuinely needs empty strings, adjust those rows after generating.

Why are the inserts batched?

One multi-row INSERT is much faster than one statement per row. The default is 100 rows per statement, which stays well inside typical packet and parameter limits; lower it if your server rejects large statements.