CSV to SQL converter
Turn a CSV into CREATE TABLE plus INSERT statements. Column types are inferred from the data, and the quoting follows the dialect you pick.
A CSV has no types — every cell is text until something decides otherwise. Turning one into SQL therefore means two jobs: guessing a sensible column type from the values you actually have, and quoting everything correctly for the database you are targeting. This page does both and shows its work. It reads the header row, scans every value in each column, proposes INT, DOUBLE, DATE, BOOLEAN or a sized VARCHAR, and lets you rename any column before it writes a line. Then it emits a CREATE TABLE and as many multi-row INSERT statements as your batch size implies, in MySQL, PostgreSQL or SQLite syntax — which differ in more places than most converters admit.
Key facts about CSV to SQL converter
| Dialects | MySQL (backtick identifiers), PostgreSQL and SQLite (double-quoted identifiers) — the type names and boolean literals differ too |
|---|---|
| Type inference | A column is INT only if every filled value is an integer, DOUBLE if every value is numeric, BOOLEAN on true/false/yes/no/t/f, DATE on YYYY-MM-DD, otherwise VARCHAR sized to the longest value |
| Leading-zero rule | A value like 01234 is treated as text, not a number — zip codes and phone numbers survive as written instead of becoming 1234 |
| Big integers | Anything past 2,147,483,647 promotes the column to BIGINT rather than overflowing an INT |
| VARCHAR sizing | Rounded up to 32, 64, 128, 255, 512 or 1000 based on the longest value; past 1000 the column becomes TEXT |
| SQLite types | SQLite has no DATE or BOOLEAN, so dates become TEXT and booleans INTEGER 0/1 — matching how SQLite actually stores them |
| Quote escaping | A single quote is doubled in every dialect; for MySQL a backslash is doubled as well, because MySQL treats it as an escape inside string literals |
| Batching | 1, 50, 100 or 500 rows per INSERT. Multi-row INSERTs are dramatically faster to load than one statement per row |
| NOT NULL | Applied only to columns where no row is blank — the tool never claims a constraint your data would violate |
| Primary key | Optional auto-increment column: AUTO_INCREMENT on MySQL, SERIAL on PostgreSQL, INTEGER PRIMARY KEY AUTOINCREMENT on SQLite. It is renamed automatically if your data already has an id column |
| Column names | Spaces and punctuation become underscores, duplicates get a numeric suffix, and a name starting with a digit is prefixed — each one editable before you export |
| Input ceiling | 10 MB of CSV text; the whole result is held in memory, so very large exports are better handled by your database's own loader |
What happens to your file
The CSV is read by a FileReader in this tab and parsed by Papa Parse; the SQL is built by string concatenation in page memory and downloaded as a Blob. No database is contacted, nothing is executed, and no row is transmitted — this tool writes a text file, it does not connect to anything. That distinction matters for the usual reason people convert a CSV to SQL: the data is often a production export sitting on someone's laptop. It never leaves this tab, there is no server-side step, and nothing is written to localStorage, so a reload clears the parsed rows entirely.
About this tool
- 1
Load the CSV
Drop the file, browse for it, or paste the text. The first row must name the columns — that is where the table's columns come from.
- 2
Pick the dialect first
MySQL, PostgreSQL or SQLite. This changes the identifier quoting, the type names, the boolean literals and the transaction keywords, so set it before you read the inferred types.
- 3
Review the inferred types
The table lists each source column, the name it will get, and the type. Anything you disagree with can be renamed here; the type follows the data, so fix a wrong type by fixing the values.
- 4
Name the table
The file name is used as a starting point, sanitised. Spaces become underscores and a leading digit gets a prefix so the identifier is valid.
- 5
Choose the statement options
CREATE TABLE and IF NOT EXISTS are on by default. Add DROP TABLE first for a clean re-import, an auto-increment id when your data has no key, and a transaction wrap so a failed row does not leave a half-loaded table.
- 6
Set the batch size and export
100 rows per INSERT is a good default for a few thousand rows. Copy the SQL into your client, or download the .sql and run it with mysql, psql or sqlite3.
| Input | .csv, .tsv or .txt with a header row, or CSV pasted into the box; up to 10 MB |
|---|---|
| Output | A .sql text file, or the same text copied to the clipboard |
| Parser | Papa Parse 5 in header mode — it sniffs comma, semicolon and tab, and honours quoted fields containing the delimiter |
| Statement shape | CREATE TABLE [IF NOT EXISTS], optional DROP TABLE IF EXISTS first, then INSERT INTO … VALUES with one tuple per row |
| Transaction wrapping | Optional — START TRANSACTION/COMMIT on MySQL, BEGIN/COMMIT on PostgreSQL and SQLite |
| Preview | The first 20,000 characters are shown in the page; the download and the clipboard always carry the whole thing |
| Browser support | Chrome, Edge, Firefox and Safari; the copy button needs a secure context |
| Offline | Works with the network off once the page has loaded |
- Set the dialect before anything else — the whole preview is regenerated against it, including the types you are about to review.
- Wrap in a transaction for anything over a few hundred rows: on failure nothing is committed, and on PostgreSQL it is also markedly faster.
- If a column you expect to be numeric shows as VARCHAR, one value in it is not a number — a stray footer row and a thousands separator are the two usual causes.
- Turn off 'Empty value → NULL' when an empty cell genuinely means an empty string rather than missing data; the default assumes missing.
- A batch of 500 rows can exceed MySQL's max_allowed_packet on a default server. Drop to 100 if the import dies with a packet error.
- Need the other direction? The SQL to CSV tool extracts rows back out of INSERT statements.
- MySQL, PostgreSQL and SQLite with dialect-correct identifiers and types
- Per-column type inference with a leading-zero guard for codes and IDs
- Editable column names, sanitised to valid identifiers
- Batched multi-row INSERTs at 1, 50, 100 or 500 rows
- Optional DROP TABLE, IF NOT EXISTS, auto-increment key and transaction wrap
- Live SQL preview, clipboard copy and .sql download
- Seeding a development database from a spreadsheet someone in the business maintains.
- Turning an exported report into a table you can actually query with joins.
- Building fixture data for tests without hand-writing a hundred INSERT statements.
- Moving a small dataset between engines by generating the target dialect directly.
- Preparing a migration file for a schema change review, where the SQL is the artefact being reviewed.
- Loading a CSV into SQLite for local analysis when the CSV import in your client refuses the file.
Related tools
View allWorks well with this5
More in Data & Dev12
Updated