---
title: "Excel to SQL Converter"
description: "Free Excel to SQL converter: upload an .xlsx file, pick a sheet, get INSERT statements or a CREATE TABLE script for any major database. In your browser."
url: "https://jamsql.com/tools/excel-to-sql/"
html_url: "https://jamsql.com/tools/excel-to-sql/"
generated: "2026-07-22T23:18:48.064Z"
---

# Excel to SQL Converter

Upload an `.xlsx` workbook and get `INSERT` statements or a `CREATE TABLE` script with inferred column types — for SQL Server, PostgreSQL, MySQL, Oracle, or SQLite. The file is parsed entirely in your browser; nothing is uploaded.

Table name  Engine SQL ServerPostgreSQLMySQLOracleSQLite Output INSERT statementsCREATE TABLECREATE TABLE + INSERTs  First row is headers  Empty fields as NULL

Excel file

**Click to choose a file** or drag an .xlsx workbook here

Sheet

Generated SQL

Copy to clipboard

Classic Oracle doesn't accept multi-row `VALUES` lists, so each row gets its own `INSERT` statement. Date and timestamp values are emitted as `DATE '…'` / `TIMESTAMP '…'` literals so they don't depend on the session's `NLS_DATE_FORMAT`.

.tool-dropzone{position:relative;border:1px dashed var(--color-border);border-radius:.5rem;background:var(--color-bg-card);min-height:240px;display:flex;align-items:center;justify-content:center;text-align:center;padding:1.5rem;transition:border-color .15s ease,background-color .15s ease}.tool-dropzone:hover,.tool-dropzone\[data-dragover=true\]{border-color:var(--color-primary);background:rgba(59,130,246,.06)}.tool-dropzone-hint{color:var(--color-text-muted);font-size:.92rem;line-height:1.6;pointer-events:none;max-width:26em}.tool-file-input{position:absolute;inset:0;width:100%;height:100%;opacity:0;cursor:pointer}!function(){var e=function(e){return document.getElementById(e)},t=e("tool-dropzone"),n=e("tool-file"),o=e("tool-file-status"),r=e("tool-sheet-row"),a=e("tool-sheet"),l=e("tool-output"),i=e("tool-status"),s=e("tool-table"),u=e("tool-engine"),d=e("tool-mode"),c=e("tool-headers"),f=e("tool-nulls"),m=e("tool-oracle-note"),v=e("tool-copy"),h=!1,g=null,p=0;function C(e){return e<10?"0"+e:String(e)}function w(e){return null==e?"":e instanceof Date?(n=(t=e).getUTCFullYear()+"-"+C(t.getUTCMonth()+1)+"-"+C(t.getUTCDate()),o=t.getUTCHours(),r=t.getUTCMinutes(),a=t.getUTCSeconds(),0===o&&0===r&&0===a?n:n+"T"+C(o)+":"+C(r)+":"+C(a)):"number"==typeof e?function(e){if(!isFinite(e))return"";if(Number.isInteger(e))return String(e);var t=String(e);return-1===t.indexOf("e")&&-1===t.indexOf("E")||(t=e.toFixed(10).replace(/0+$/,"").replace(/\\.$/,"")),t}(e):"boolean"==typeof e?e?"true":"false":"object"==typeof e?Array.isArray(e.richText)?e.richText.map(function(e){return e.text}).join(""):void 0!==e.result?w(e.result):void 0!==e.error?"":void 0!==e.text?w(e.text):void 0!==e.hyperlink?String(e.hyperlink):"":String(e);var t,n,o,r,a}function x(e,t){var n={sql:"",rows:0,columns:0,warning:""};if(!e)return n;var o=function(e){var t=e.columnCount||0,n=\[\];return t?(e.eachRow({includeEmpty:!0},function(e,o){for(var r=\[\],a=!1,l=1;l<=t;l++){var i=w(e.getCell(l).value);""!==i&&(a=!0),r.push(i)}a&&n.push({f:r,line:o})}),{rows:n,colCount:t}):{rows:n,colCount:0}}(e),r=o.rows,a=o.colCount;if(!a||0===r.length)return n;var l=t.headers?r\[0\]:null,i=t.headers?r.slice(1):r;i.length>JamSqlGen.ROW\_CAP&&(i=i.slice(0,JamSqlGen.ROW\_CAP),n.warning="Showing the first "+JamSqlGen.ROW\_CAP+" rows — for bigger loads use a bulk import tool.");var s=JamSqlGen.columnNames(l?l.f:\[\],!!t.headers,a).map(function(e){return JamSqlGen.identSql(e,t.engine)}),u=JamSqlGen.identSql(t.tableName.trim()||"my\_table",t.engine),d=JamSqlGen.inferColumns(i,a),c=\[\];return"create"!==t.mode&&"both"!==t.mode||c.push(JamSqlGen.buildCreateTable(u,s,d,t.engine)),("insert"===t.mode||"both"===t.mode)&&i.length>0&&c.push(JamSqlGen.buildInserts(u,s,d,i,t.engine,!!t.emptyAsNull)),n.sql=c.join("\\n\\n"),n.rows=i.length,n.columns=a,n}function b(){var e="oracle"===u.value;m.hidden=!(e&&"create"!==d.value);var t=function(){if(!g)return null;var e=g.worksheets;return e\[a.value?parseInt(a.value,10):0\]||e\[0\]||null}();if(!t)return l.textContent="",i.textContent="",void i.classList.remove("tool-error");var n=x(t,{tableName:s.value,engine:u.value,mode:d.value,headers:c.checked,emptyAsNull:f.checked});if(l.textContent=n.sql,!n.sql)return i.textContent="That sheet has no data.",void i.classList.remove("tool-error");var o=n.rows+" row"+(1===n.rows?"":"s")+", "+n.columns+" column"+(1===n.columns?"":"s");i.textContent=n.warning?o+" · "+n.warning:o,i.classList.toggle("tool-error",!1),!h&&window.umami&&"function"==typeof window.umami.track&&(h=!0,window.umami.track("tool-excel-to-sql-generate",{engine:u.value,mode:d.value}))}function S(e){if(window.ExcelJS)e();else{if(p>100)return o.textContent="Could not load the Excel parser. Please reload the page.",void o.classList.add("tool-error");p++,setTimeout(function(){S(e)},150)}}function E(e){if(e){g=null,r.hidden=!0,l.textContent="",i.textContent="",o.classList.remove("tool-error"),o.textContent="Reading "+e.name+"…";var t=new FileReader;t.onerror=function(){o.textContent="Could not read that file.",o.classList.add("tool-error")},t.onload=function(){S(function(){var n=new window.ExcelJS.Workbook;n.xlsx.load(t.result).then(function(){if(!n.worksheets.length)return o.textContent="That workbook has no sheets.",void o.classList.add("tool-error");g=n,function(e){var t=e.worksheets;a.innerHTML="",t.forEach(function(e,t){var n=document.createElement("option");n.value=String(t),n.textContent=e.name,a.appendChild(n)}),r.hidden=t.length<2}(n),o.textContent=e.name+" — "+n.worksheets.length+" sheet"+(1===n.worksheets.length?"":"s"),b()}).catch(function(e){o.textContent="Could not read that file — is it a valid .xlsx workbook? "+(e&&e.message?e.message:""),o.classList.add("tool-error")})})},t.readAsArrayBuffer(e)}}n.addEventListener("change",function(){E(n.files&&n.files\[0\])}),\["dragenter","dragover"\].forEach(function(e){t.addEventListener(e,function(e){e.preventDefault(),t.setAttribute("data-dragover","true")})}),\["dragleave","drop"\].forEach(function(e){t.addEventListener(e,function(e){e.preventDefault(),t.removeAttribute("data-dragover")})}),t.addEventListener("drop",function(e){var t=e.dataTransfer&&e.dataTransfer.files;t&&t\[0\]&&E(t\[0\])}),a.addEventListener("change",b),\[s,u,d,c,f\].forEach(function(e){e.addEventListener("input",b),e.addEventListener("change",b)}),v.addEventListener("click",function(){var e=l.textContent;if(e){var t=function(){v.dataset.copied="true",v.textContent="Copied!",setTimeout(function(){delete v.dataset.copied,v.textContent="Copy to clipboard"},1500)};if(navigator.clipboard&&navigator.clipboard.writeText)navigator.clipboard.writeText(e).then(t);else{var n=document.createElement("textarea");n.value=e,document.body.appendChild(n),n.select(),document.execCommand("copy"),document.body.removeChild(n),t()}}})}()

## How type inference works

Unlike a CSV file, an `.xlsx` workbook already stores each cell with a real type — number, date, boolean, or text — so the converter reads that type directly instead of re-parsing displayed text. It still scans *every* value in every column before picking a `CREATE TABLE` type, the same way the [CSV to SQL converter](/tools/csv-to-sql/) does:

-   All-integer columns become `INT`, promoted to `BIGINT` when any value exceeds the 32-bit range (±2,147,483,647).
-   Decimal columns become `DECIMAL(p,s)` with precision and scale sized from the widest value actually present.
-   Date cells with no time component become `DATE`; date cells with a time component map to the engine's native datetime type (`DATETIME2`, `TIMESTAMP`, `DATETIME`).
-   Excel's `TRUE/FALSE` cells map to the engine's boolean equivalent.
-   Everything else becomes a text type sized to the next bucket above the longest value (50 / 100 / 255 / 1000, then `MAX`/`TEXT`/`CLOB`).
-   A text cell holding something like `007` — a zip code or product code typed as text so Excel doesn't strip the leading zero — stays text in the generated schema too.
-   Columns with no empty cells are marked `NOT NULL`.

Formula cells are read by their last-calculated result — the cached value Excel wrote when the file was saved — not re-evaluated. A formula that last resolved to an error is treated as an empty cell. As with any inference tool, treat the generated DDL as a solid first draft: no primary keys, foreign keys, or indexes are guessed, and a column that looks numeric in your sample may still be semantically text.

## Multiple sheets

If the uploaded workbook has more than one sheet, a sheet picker appears below the upload area listing every sheet by name. The converter reads the first sheet by default; switching the dropdown re-generates the SQL from the newly selected sheet immediately, without re-uploading the file.

## Engine differences that matter when bulk-inserting

-   **SQL Server** — a single `INSERT … VALUES` statement is hard-capped at 1,000 row value expressions (error 10738), so the converter batches at 500 rows per statement. Text columns are generated as `NVARCHAR` rather than `VARCHAR`, since spreadsheet text is Unicode in practice.
-   **Oracle** — classic Oracle doesn't support multi-row `VALUES` lists (that arrived in Database 23ai), so the output is one `INSERT` per row. Dates are emitted as `DATE '2024-03-01'` and `TIMESTAMP '…'` literals so the script doesn't depend on a session's `NLS_DATE_FORMAT`.
-   **Identifier quoting** — SQL Server uses `[brackets]`, MySQL uses `` `backticks` ``, and PostgreSQL, Oracle, and SQLite use `"double quotes"`. Column headers with spaces or special characters (common in spreadsheets — "First Name", "Order #") get quoted automatically; simple lowercase names don't.
-   **MySQL** — multi-row `VALUES` has no row cap, but very large statements can exceed `max_allowed_packet`; 500-row batches keep each statement comfortably small.
-   **SQLite** — there are no `VARCHAR(n)` semantics, so text, dates, and datetimes all become `TEXT` — the idiomatic way to store ISO-8601 values in SQLite.

This tool is for ad-hoc loads, test fixtures, and seed scripts built from a spreadsheet. For recurring or multi-megabyte imports, use the engine's bulk loader — `BULK INSERT`/`bcp`, `COPY`, `LOAD DATA INFILE`, SQL\*Loader, or `.import` — which is orders of magnitude faster than INSERT statements.

## Frequently asked questions

### How do I convert an Excel file to SQL INSERT statements?

Click the upload area above and choose an `.xlsx` file (or drag one in), set the table name and target engine, and copy the generated INSERT statements. The first row of the sheet is treated as column headers by default. Everything is parsed and converted locally in your browser — the file is never uploaded anywhere.

### Does this tool support .xls files?

No, only the modern `.xlsx` format (Office Open XML, used by Excel 2007 and later, and exported by Google Sheets and LibreOffice Calc). The legacy `.xls` binary format from Excel 97-2003 is not supported. If you have an `.xls` file, open it in Excel, Google Sheets, or LibreOffice Calc and use "Save As" / "Download" to save it as `.xlsx` first.

### What happens if my workbook has multiple sheets?

A sheet picker appears once the workbook is parsed, listing every sheet by name. The first sheet is selected by default; switching sheets regenerates the SQL immediately from the newly selected sheet's data without re-uploading the file.

### How many rows can I convert?

The converter generates SQL for up to 5,000 data rows per sheet. If the sheet has more, it emits the first 5,000 and shows a warning instead of silently truncating. For bigger loads use a bulk import tool — `BULK INSERT` or `bcp` for SQL Server, `COPY` for PostgreSQL, `LOAD DATA INFILE` for MySQL, SQL\*Loader for Oracle, or `.import` in the SQLite CLI.

### How are data types chosen for CREATE TABLE?

Excel cells already carry a real type — number, date, boolean, or text — and the converter reads that directly rather than re-guessing it from displayed text. Every value in every column is then scanned to pick the narrowest SQL type that fits all of them: all-integer columns become `INT` (`BIGINT` when a value exceeds the 32-bit range), decimal cells become `DECIMAL(p,s)` sized from the widest value, date cells become `DATE` or the engine's datetime type depending on whether a time component is present, and Excel's `TRUE/FALSE` cells map to the engine's boolean equivalent. Everything else becomes a text type sized to the next bucket above the longest value. Columns with no empty cells are marked `NOT NULL`.

### How are empty cells and formulas handled?

By default empty cells become `NULL`. Uncheck "Empty fields as NULL" to insert empty strings (`''`) into text columns instead. Formula cells are read by their last-calculated result (the value Excel had cached when the file was saved) — the formula itself is not evaluated or included. A formula that last evaluated to an error (like `#DIV/0!`) is treated as empty.

### Is my spreadsheet uploaded anywhere?

No. The workbook is read and parsed entirely in your browser using the open-source ExcelJS library, vendored locally on this page rather than loaded from a CDN. The file never leaves your machine and no network request is made with its contents — you can disconnect from the internet after the page loads and it keeps working.

## Loading spreadsheets into a real database?

Jam SQL Studio is a free desktop SQL client for SQL Server, PostgreSQL, MySQL, Oracle, and SQLite — import CSV, XLSX, and JSON files straight into a new or existing table with a guided wizard, browse and edit table data in a spreadsheet-like grid, and export results in any format.

[Download Free](/#download) [Table Explorer Docs](/docs/table-explorer/)

Free for personal use • No account required • Mac, Windows, Linux

## More free SQL tools

[

### All Free SQL Tools

The full collection — formatters, converters, and generators for everyday SQL work.

](/tools/)[

### CSV to SQL Converter

Paste CSV or spreadsheet data and get INSERT statements or a CREATE TABLE script with inferred column types.

](/tools/csv-to-sql/)[

### CSV to JSON Converter

Paste or upload CSV and get a pretty-printed JSON array or NDJSON, with types inferred per column.

](/tools/csv-to-json/)[

### SQL Data Type Converter

Map data types across SQL Server, PostgreSQL, MySQL, Oracle, and SQLite — with precision and pitfall notes.

](/tools/sql-data-type-converter/)