Skip to content

Formatters & Code

CSV to SQL INSERT Statements

Generate INSERT statements from any CSV file.

Runs in your browser
CSV · source
first row = header
lines: 4chars: 131size: 131 B
SQL INSERT statements · result
lines: 3chars: 323size: 323 B
live

Understanding CSV → SQL

The cleanest export, the messiest import.

Why every CSV-to-SQL tool eventually has to handle commas inside quotes, NULL vs empty, and the date that nobody can agree how to parse.

What the converter is really doing.

A CSV-to-SQL converter parses each row, infers a column type, escapes each value according to the target dialect, and emits INSERT statements. Three of those steps are where almost every bug lives. Parsing has to handle quoted fields with embedded delimiters, embedded newlines, and double-double-quote escaping. Type inference has to decide between INTEGER, FLOAT, DATE and TEXT from a small sample. Escaping has to match the target database's rules — quote characters, NULL representations, identifier quoting.

The quoting rules.

Standard CSV (RFC 4180): fields containing the delimiter, a quote, or a newline must be quoted with double quotes; embedded double quotes are escaped by doubling them. A field like She said "hi" becomes "She said ""hi""". Many real-world CSV files break this rule — single quotes around fields, backslash- escaped quotes, mixed delimiters — and every robust parser has to handle the deviations.

Type inference from a sample.

A column with values "1", "42", "1000" is probably INTEGER. With "1.5" mixed in it becomes FLOAT. With "2026-05-13" it's DATE; with "true" / "false" it's BOOLEAN. The decision flips when even one value doesn't fit — a single "N/A" in a numeric column forces TEXT. Sensible converters report the inferred type per column so the user can override; silently picking TEXT for a column of integers because of one stray value turns every downstream query into a CAST.

NULL vs empty string.

CSV has no native concept of NULL — the field is either absent (two consecutive delimiters) or contains a value. Different exporters use different conventions: empty-string-means-null, the literal word "NULL", "\N" (the MySQL/Postgres tab- delimited convention), "NA", "—". The right import behaviour is configurable: tell the converter which token represents NULL, and it emits SQL NULL there instead of an empty string. The wrong-default version is "empty equals empty string" which silently breaks aggregations and joins.

A worked row.

Input row: 7,"O'Brien, Q",2026-05-13,"She said ""hi""" with column names id, name, joined, note. Inferred types: INTEGER, TEXT, DATE, TEXT. Quotes inside the name field need to be doubled in target SQL string literals (PostgreSQL syntax): 'O''Brien, Q'. The double-double-quote in the note unwraps to a single double-quote, then needs no further escaping inside SQL single-quoted strings. The complete statement is INSERT INTO t (id, name, joined, note) VALUES (7, 'O''Brien, Q', '2026-05-13', 'She said "hi"');.

Single row, four columns

commas inside quotes, embedded quote, ISO date

Parse → infer types → escape per target dialect → emit INSERT

7, "O'Brien, Q", 2026-05-13, "She said ""hi"""

= INSERT … VALUES (7, 'O''Brien, Q', '2026-05-13', 'She said "hi"');

Dialect choices.

SQL dialects diverge on more things than you'd expect: identifier quoting (double- quotes in standard SQL/Postgres, backticks in MySQL, square brackets in T-SQL), string escaping (doubled-single-quotes everywhere, plus backslash escapes in MySQL by default), date formats (Postgres flexible, MySQL stricter), and how to express inserting many rows at once. A converter that targets "SQL" generically usually targets ANSI SQL and lets the user pick. Always test the output against your real database — generic SQL almost works, doesn't quite.

Performance: batch your INSERTs.

One INSERT per row is the wrong way to import 100,000 rows. Modern databases support multi-row inserts: INSERT INTO t (a, b) VALUES (1, 'x'), (2, 'y'), (3, 'z'). For large imports use COPY (Postgres) or LOAD DATA INFILE (MySQL) directly — they bypass the SQL parser and run orders of magnitude faster. The converter here emits standard INSERTs for portability; for a 10M-row import, generate a CSV that COPY can consume directly.

Frequently asked questions

Quick answers.

Is my data privacy protected?

Yes. The conversion logic runs locally in your browser, so your CSV data is never transmitted to our servers.

How does the tool handle data types?

It attempts to detect numbers and booleans to omit quotes, while wrapping strings in single quotes. You should review the output for specific SQL dialect requirements like date formatting.

Can I use a custom table name?

Yes. You can specify the target table name in the configuration field to ensure the generated `INSERT` statements match your database structure.

What happens if my CSV has a header row?

The tool uses the first row of your CSV to define the column names in the resulting SQL statement. If your CSV lacks headers, you can manually define them in the settings.

People also search for

Related tools

More in this room.

See all in Formatters & Code