Home · Free tools · Excel to SQL

Excel to SQL

Drop a .xlsx or .csv, name the table, pick the database. You get a CREATE TABLE whose column types are inferred from the data — integers, decimals, dates, booleans, text sized to the longest value — and INSERT statements in batches you can paste into a console or run as a file. Reference numbers with leading zeros stay text, amounts with thousands separators become numbers, and nothing is uploaded.

Your spreadsheet

Drop .xlsx or .csv here, or click to choose

Nothing is uploaded. The file is read by JavaScript in this tab and never leaves your computer — no server sees it, and closing the tab throws it away.

How to convert an Excel sheet to SQL

  1. Drop the file. A .xlsx with several sheets shows a sheet picker; a CSV is read with its encoding detected, so accented text and CJK survive.
  2. Check the inferred types. The column table shows what each column became. A column of numbers with a leading zero is kept as text on purpose; change the header or the data if you want it numeric.
  3. Pick the dialect and batch size. Quoting, boolean literals and the maximum rows per INSERT differ between MySQL, PostgreSQL, SQLite and SQL Server; the output follows the one you chose.
  4. Copy or download. Copy the SQL to the clipboard for a console, or download the .sql file to run with your client of choice.

What the types are inferred from

Every value in a column is looked at, not just the first few rows. A column becomes an integer only if every non-empty value is a whole number without a leading zero; a decimal if every value parses as a number once currency symbols and thousands separators are removed; a date or timestamp if every value is ISO-shaped (2026-09-06, optionally with a time); a boolean if every value is true/false or yes/no. Anything else is text, sized to the longest value with headroom — VARCHAR(50), VARCHAR(100) — and switched to TEXT when that would exceed 255 characters. Empty cells become NULL in every type.

The one rule that surprises people is deliberate: 00012345 is text. Invoice numbers, account numbers, postcodes and product codes carry their leading zeros as part of the identifier, and a column that loses them on import is the first thing a reconciliation trips over later.

Four dialects, four sets of details

  • MySQL / MariaDB — backtick-quoted identifiers, DECIMAL(18,4) for money, TRUE/FALSE, VARCHAR up to 255 then TEXT.
  • PostgreSQL — double-quoted lower-case identifiers, NUMERIC(18,4), TEXT for strings (it costs nothing there), TIMESTAMP for dates.
  • SQLite — its four storage classes: INTEGER, REAL, TEXT; dates stay text, which is what SQLite itself recommends.
  • SQL Server — bracketed identifiers, NVARCHAR with N'…' literals so non-Latin text survives, BIT for booleans, and INSERTs capped at 1,000 rows each because that is the server's own limit per statement.

Column names become identifiers

Headers are turned into safe identifiers: spaces and punctuation become underscores, everything is lower-cased, a leading digit gets an underscore in front, and a repeated header gets a number (amount, amount_2). Empty headers are named by position. The original header text is not lost — it is visible in the column table above the SQL, so you can rename in the sheet and drop it again if the generated name is not what you want.

What it does not do

  • No primary keys, indexes or constraints are guessed; add them after the load, when you know which column is actually unique.
  • Formulas are converted as the value Excel last calculated, not as the formula.
  • Merged cells, formatting and comments are ignored; only the grid is read.
  • Very large sheets work, but a million-row INSERT script is a slow way to load a database — for that size, export CSV and use the database's bulk loader.

Nothing leaves this tab

The file is parsed and the SQL is written by JavaScript in your browser. The customer list or price table you are about to load into a database is not uploaded to this site or anywhere else.

Questions people ask

How do I convert Excel to SQL insert statements?

Drop the workbook, pick the sheet, name the table, and the INSERT statements are generated in batches — 500 rows each by default — with a CREATE TABLE in front. Copy them or download the .sql file.

Does it work with CSV files?

Yes. A CSV is read with its delimiter and encoding detected, so a semicolon-separated export from a European locale or a GBK/Shift-JIS file comes through intact.

Why is my numeric column typed as VARCHAR?

One of three reasons: a value has a leading zero (kept as text on purpose), a value is not a number at all (a stray "n/a" or a note), or the numbers use a thousands separator that could not be told apart from a decimal point. Sort the column in the sheet and look at the ends; the odd value is usually there.

Can I load the file straight into the database instead?

For a one-off table this script is the quickest route. For a feed that arrives every week, the TableDI desktop app keeps the mapping and the types as a job and writes to PostgreSQL, MySQL or SQLite directly, so the second week is a drop-and-run.

Are my files uploaded anywhere?

No. The file is read by JavaScript running in this tab, using the browser's own DecompressionStream to unzip .xlsx and a parser that runs on your machine. There is no server call in the page — you can watch the network tab while you use it. Close the tab and the data is gone.

Does it work with old .xls files?

Not directly. The .xls format is a different, binary format from Excel 97. Open it in Excel, LibreOffice or Numbers and save as .xlsx or .csv, then come back. The tool tells you this rather than failing silently.

Do this on your own machine instead

TableDI is a desktop spreadsheet workspace that runs entirely on your machine. Import the file, fix it, chart it — nothing is uploaded, and there is no account to create.

Free forever, not a trial — no account, no card. macOS today; a Windows build is in progress. What the paid tier adds.

Last reviewed 2026-09-01 by the TableDI team. Something wrong on this page? Tell us — it is one inbox, read by the people who build TableDI.