Command Palette

Search for a command to run...

CSV to SQL: Turn a Spreadsheet Into INSERT Statements Without the Quote Bugs

CSV to SQL: Turn a Spreadsheet Into INSERT Statements Without the Quote Bugs

T
Toolz Team
|Aug 23, 2026|17 min read

Part of the Data Tools collection

The task that finally made me build this was boring and it cost me an hour I did not have. A client handed me a spreadsheet of 1,800 product rows and asked me to load it into their staging database before a demo the next morning. No API, no import screen, just a CSV and a MySQL table waiting for it. I did what everyone does the first time: I opened the file, wrote a couple of INSERT statements by hand to get the shape right, and started copying values in. Three rows later a product name with an apostrophe in it, O'Brien's Tools, broke the whole statement, because the single quote closed the string early and MySQL choked on the rest. That is the moment you realize hand-writing SQL from a spreadsheet is not a five-minute job, it is a quoting minefield with 1,800 chances to step wrong. So I built the CSV to SQL converter, and this guide is the reasoning behind every option in it.

TL;DR: A CSV to SQL converter reads a CSV file and generates the CREATE TABLE and INSERT statements a database needs to store it. The Toolz tool parses the file with an RFC 4180 state machine, infers whether each column is an integer, decimal, boolean, or text, quotes identifiers for MySQL, PostgreSQL, or SQLite, escapes every value correctly, and turns empty cells into NULL. Paste the CSV, pick your dialect, and copy a script you can run straight away. Everything runs client-side: no upload, no signup, works offline.

I build SaaS products on Laravel and React and I ship WordPress plugins, so loading tabular data into a database is a weekly chore rather than a one-off. Sometimes it is a client export, sometimes a seed file for a fresh environment, sometimes a quick fixture for a test. CSV is always the format it arrives in, and SQL is always where it needs to end up. Getting from one to the other by hand is exactly the kind of repetitive, error-prone work a browser tool should erase, so this is the guide I wish I had when that apostrophe broke my import.

What is a CSV to SQL converter?

A CSV to SQL converter takes rows of comma-separated values and produces the SQL statements that create a table and load the data into it. CSV itself is only loosely standardised - RFC 4180 describes the common form and is explicit that it documents existing practice rather than dictating it. It reads the first row as the column names, treats every following row as a record, and emits two things: a CREATE TABLE statement that defines the columns with sensible types, and a set of INSERT statements that carry the values. The output is a plain SQL script you can paste into a database client such as TablePlus or DBeaver, drop into a migration, or pipe into the mysql, psql, or sqlite3 command line to build and populate the table in one step.

The reason the category exists is that the translation is fiddly in ways that are easy to underestimate. Every text value has to be wrapped in single quotes. Every single quote inside a value has to be doubled so it does not terminate the string. Numbers and booleans must be left unquoted or the database will store them as text and your WHERE price > 100 will behave strangely. Empty cells usually need to become NULL rather than an empty string. Column names with spaces or reserved words have to be quoted with the right character for your database. Miss any one of these across a few thousand rows and the whole batch fails, often with an error that points at the wrong line. A converter applies all of these rules the same way every time, which is the entire value proposition.

How does the tool decide each column's type?

This is the part that separates a useful converter from a dumb one. A naive tool makes every column TEXT and calls it done, which technically works but gives you a table where numbers sort as strings and you cannot do arithmetic without casting. The Toolz CSV to SQL tool instead scans every value in a column and picks the narrowest type that fits all of them.

The logic is straightforward once you see it. If every non-empty value in a column is a whole number, the column becomes an integer type. If every value is numeric but some have decimal points, it becomes a floating type. If every value is the word true or false, it becomes a boolean. Anything else, including mixed content and anything with letters, falls back to text. There is one deliberate exception that catches people out in a good way: a value like 007 or 00123 stays text, not an integer, because a leading zero almost always means the column is an ID, a zip code, or a phone number where the zero is significant and would be lost if stored as a number. That single rule has saved me from silently corrupting more than one product SKU column.

You can turn inference off if you would rather every column be text, which is the safe choice when you plan to alter the types yourself after loading. But for the common case, letting the tool infer types means the generated CREATE TABLE matches the data instead of flattening it, and the table is usable the moment it exists.

Which SQL dialect should I choose?

SQL is a standard the way English spelling is a standard, which is to say every database has its own accent. The dialect you pick changes three things in the output: how identifiers are quoted, what the type names are called, and how true and false are written. Here is how the four options differ.

Concern MySQL PostgreSQL SQLite Standard SQL
Identifier quoting Backticks `col` Double quotes "col" Double quotes "col" Double quotes "col"
Integer type INT INTEGER INTEGER INTEGER
Decimal type DOUBLE DOUBLE PRECISION REAL REAL
Boolean type TINYINT(1) BOOLEAN INTEGER BOOLEAN
Text type VARCHAR(255) TEXT TEXT TEXT
Boolean values 1 / 0 TRUE / FALSE 1 / 0 TRUE / FALSE

The practical guidance is to match the dialect to the database you are actually loading into, because the differences are not cosmetic. MySQL will reject the double-quoted identifiers PostgreSQL wants unless you are in ANSI mode, and PostgreSQL has no TINYINT. SQLite has no real boolean type at all, so booleans become integers, which is why the tool writes 1 and 0 for both MySQL and SQLite but TRUE and FALSE for PostgreSQL and standard SQL. If you are not sure or you are writing something portable, standard SQL is the most conservative choice. Once the statements are generated you can always run them through the SQL formatter to pretty-print the output before it goes into a migration file.

How do I convert a CSV to SQL with the tool?

The flow is deliberately short. Paste your CSV into the input box, or click Load Sample to see a worked example with an id, a name, a role, a boolean, and a salary column.

Set the table name to whatever the target table should be called, and pick your SQL dialect. Then decide on the output options. Leave "Include CREATE TABLE" on if the table does not exist yet, or turn it off to generate only the INSERT statements when you are loading into a table that is already there. Keep "Infer column types" on for a typed table, or off to make everything text. Choose "Multi-row INSERT" for one compact statement with many value tuples, which loads fastest, or turn it off to get one INSERT per row, which is friendlier to version control and lets you run rows individually. Leave "Empty cells as NULL" on unless you specifically want empty strings stored.

The delimiter can be auto-detected or set by hand. Auto-detect scores comma, semicolon, tab, and pipe by how consistently each one splits the first several lines into the same number of columns, which correctly handles European semicolon files and tab-separated exports. Click Convert to SQL and the output appears with a count of rows and columns, plus any warnings about duplicate column names or ragged rows. Copy it and run it. If the export arrived without a header line, turn off "First row is header" and the tool names the columns column_1, column_2, and so on, then treats every row as data.

Why does correct value escaping matter so much?

Because incorrect escaping is not just a bug, it is a class of security vulnerability. The apostrophe that broke my first import by hand is the same mechanism behind SQL injection: a single quote inside a value, if not escaped, ends the string early and lets whatever follows be interpreted as SQL. In an application you solve this with parameterized queries, where the database driver keeps values and code strictly separate. When you are generating a static SQL script from a CSV, you do not have that separation, so the escaping has to be correct in the generated text itself.

The tool follows the ANSI SQL rule: a text value is wrapped in single quotes, and any single quote inside the value is doubled. So O'Brien's Tools becomes 'O''Brien''s Tools', which every one of the supported databases reads back as the original string. Numbers and booleans are emitted without quotes so they are stored as the right type, and identifiers are quoted with the dialect's own character so a column called order or select does not collide with a reserved word. This is exactly the kind of tedious correctness that humans get wrong under time pressure and a tool gets right every time, which is the whole point of automating it. If you are curious about how the escaping compares across formats, the CSV to JSON converter faces the same problem from the JSON side, where the escape character is a backslash rather than a doubled quote.

Is it safe to convert sensitive CSV data online?

For this tool, yes, and the reason is architectural rather than a promise on a page. Every step, parsing the CSV, inferring column types, escaping values, and building the statements, runs as JavaScript inside your own browser tab. There is no upload, no server round trip, and nothing is logged or stored. You can prove it by opening your browser's network tab and clicking Convert: no request leaves the page. Once the page has loaded you can disconnect from the internet entirely and it keeps generating SQL.

That matters because the CSVs people convert to SQL are often the most sensitive files a business has. Customer tables, order histories, user records, and pricing data all travel as CSV before they land in a database. A converter that uploads your file to a server, however well meant, turns a private spreadsheet into someone else's log entry. Client-side processing removes the question entirely: the data never leaves the machine it started on. That default is deliberate across every tool on toolz.dev, and I wrote up the longer argument in the data privacy guide for online tools for anyone who wants the full reasoning.

Where does CSV to SQL fit in a real workflow?

The conversion is rarely the whole job, it is one station in a pipeline. The pattern I hit most often is seeding: a client sends a spreadsheet, I convert it to a SQL script, and I run that script to populate a staging or development database so the app has realistic data to work against. Because the output is a plain script rather than a live connection, it is easy to check into a repo as a seed file, review in a pull request, and re-run in any environment.

The tools around it depend on what the data is doing next. If I need to eyeball the file as a sortable grid before converting, the CSV viewer renders the same RFC 4180 parse as a table so I can spot a malformed row before it becomes a malformed INSERT. If the destination is an API or a config file rather than a database, the CSV to JSON converter is the right hop instead, and its sibling JSON to CSV handles the reverse when I need to hand data back as a spreadsheet. And once the SQL exists, the SQL formatter tidies it into something readable for a migration. None of these upload your data, so you can chain them on the same private file without a second thought. If you are assembling a kit for this kind of data work, my web developer toolkit guide walks through how the pieces connect.

What are the limits worth knowing about?

Honesty about limits is part of trusting a tool. The converter generates standard CREATE TABLE and INSERT statements, which means it does not infer primary keys, foreign keys, indexes, or column constraints, because none of that information exists in a flat CSV. It picks a reasonable type for each column, but VARCHAR(255) for MySQL text is a default, not a measurement; if you have a column of long descriptions you may want to widen it to TEXT after loading, and if you have a column that should be DATE or DATETIME you will want to alter it, since the tool treats dates as text to avoid guessing a format wrong.

The multi-row INSERT is compact and fast, but very large files produce a single very long statement, and some databases cap the size of one statement or the number of placeholders. If you are loading tens of thousands of rows and hit a limit, switch to one INSERT per row, which trades a bigger script for statements a database will always accept. Finally, the tool is for generating load scripts, not for streaming a multi-gigabyte file, because the whole input lives in browser memory. For everyday exports, seed files, and fixtures, which is what most people actually have, none of these limits bite. Knowing they exist is just the difference between using a tool well and being surprised by it.

Frequently asked questions

How do I convert a CSV file to SQL? Paste the CSV into the CSV to SQL converter, set the table name, and choose your SQL dialect. It reads the header row as column names, infers each column type, and generates a CREATE TABLE plus INSERT statements you can copy and run in your database. Everything happens in your browser, so the file is never uploaded.

Which SQL databases does it support? The converter outputs statements for MySQL, PostgreSQL, SQLite, and standard SQL. The dialect you pick controls identifier quoting and the type and boolean syntax, so the script runs in that database without edits. MySQL uses backticks and TINYINT(1) booleans, while PostgreSQL and standard SQL use double quotes and TRUE or FALSE.

How does it decide the column types? Each column is checked against every value in the data. If all non-empty values are whole numbers the column becomes an integer type, all numbers become a decimal type, all true or false values become a boolean type, and anything else becomes text. A value with a leading zero such as 007 stays text because it is usually a significant identifier. You can turn inference off to make every column text.

Does it create the table or only the inserts? Both by default. It emits a CREATE TABLE statement with the inferred column types followed by the INSERT statements. You can turn the CREATE TABLE off when the table already exists and you only need to load rows.

How are quotes and special characters handled? Text values are wrapped in single quotes and any single quote inside a value is doubled, which is the standard SQL escape, so O'Brien becomes 'O''Brien'. Numbers and booleans are left unquoted, and identifiers are quoted with backticks for MySQL or double quotes for the other dialects, so a reserved word like order does not break the statement.

What happens to empty cells? By default an empty cell becomes NULL, which is usually what you want for a missing value. If you prefer to store an empty string instead, turn off the empty-as-NULL option and empty cells become two single quotes.

Can I convert a CSV that has no header row? Yes. Turn off the header option and the tool names the columns column_1, column_2, and so on, then treats every row as data. This is useful for raw exports that ship without a header line.

Are my CSV files uploaded anywhere? No. Parsing and SQL generation run as JavaScript in your browser. Nothing is transmitted, logged, or stored, and the tool keeps working offline once loaded, which you can confirm by watching the network tab while you convert.

Comments

0 comments

0/2000 characters

No comments yet. Be the first to share your thoughts!