CSV to SQL Converter

Paste CSV with a header row and get ready-to-run SQL: column types inferred from the data, values escaped for your database. The file is processed in your browser only.

CSV → SQL

Input

Settings

History

Load from URL

When SQL beats an import wizard

Database import tools are powerful but fiddly: COPY needs server file access, LOAD DATA LOCAL INFILE is often disabled, and GUI wizards guess types badly. Plain SQL statements work everywhere — a migration file, a psql or sqlcmd session, a seed script in your repository, or the query window of a hosted database console. Converting a CSV into INSERTs is the quickest way to get a spreadsheet, a report export or a small reference table (countries, price lists, feature flags) into a database you control.

How the CSV is read

The first row must be a header; its cells become column names. Empty header cells are named column_1, column_2 and so on, and duplicate names get a suffix. Rows longer than the header add extra column_N columns, and missing trailing fields become NULL. Parsing follows RFC 4180, so quoted commas, doubled quotes and multi-line cells work as in Excel.

Each cell is then typed with the same cautious rules as CSV to JSON:

  • An empty cell becomes NULL, not an empty string.
  • Exactly true and false become booleans.
  • Plain decimals such as 42 or 1520.50 become numbers, keeping their written digits.
  • Anything else stays text — including 00123, +65 9123 4567, 1e5 and TRUE — so identifiers never lose leading zeros.

Column types per database

The table definition is chosen by looking at every value in each column. A column of small whole numbers gets INTEGER (INT in MySQL and SQL Server); bigger ones get BIGINT. A column mixing 88.00 and 1520.50 becomes NUMERIC in PostgreSQL or DECIMAL(6,2) in MySQL, SQL Server and standard SQL, sized from the widest value. Values like 2024-03-11 produce a DATE column, and full timestamps a timestamp type; SQLite, which has neither, keeps them as TEXT.

Text columns are TEXT in PostgreSQL and SQLite, NVARCHAR(MAX) in SQL Server, and VARCHAR(n) in MySQL and standard SQL, where n is the longest value in characters. A column where one row says n/a and the rest are numbers is typed as text, because a numeric column would reject that row.

Options

Table name sets the target (default records); staging.import_2026 is quoted as schema and table. Dialect selects PostgreSQL, MySQL, SQLite, T-SQL (SQL Server) or Standard SQL. Include CREATE TABLE can be switched off to append rows to an existing table. One multi-row INSERT groups up to 1,000 rows per statement, which loads far faster than single-row inserts.

All identifiers are quoted in the dialect’s style, so header names with spaces or reserved words such as from and select are valid. Escaping follows each database’s rules for apostrophes, backslashes (MySQL) and Unicode (SQL Server’s N prefix). Review the output in the SQL formatter; nothing you paste is sent anywhere.

Examples

Customer export for PostgreSQL

joined becomes a DATE column, balance a NUMERIC column, and the quoted name keeps its comma and inner quotes.

Input
id,name,city,joined,balance
1,"Tan, Aisha",Singapore,2024-03-11,1520.50
2,Ben Okafor,Lagos,2023-11-02,88.00
3,"Chloé ""CJ"" Martin",Paris,2025-01-20,-12.75
Output
CREATE TABLE "customers" (
  "id" INTEGER,
  "name" TEXT,
  "city" TEXT,
  "joined" DATE,
  "balance" NUMERIC
);

INSERT INTO "customers" ("id", "name", "city", "joined", "balance") VALUES (1, 'Tan, Aisha', 'Singapore', '2024-03-11', 1520.50);
INSERT INTO "customers" ("id", "name", "city", "joined", "balance") VALUES (2, 'Ben Okafor', 'Lagos', '2023-11-02', 88.00);
INSERT INTO "customers" ("id", "name", "city", "joined", "balance") VALUES (3, 'Chloé "CJ" Martin', 'Paris', '2025-01-20', -12.75);
Open this example in the tool

ZIP codes and gaps into MySQL

Leading-zero ZIP codes stay text in a VARCHAR column, empty cells are inserted as NULL, and all rows share one INSERT.

Input
store,zip,opened,manager
Downtown,00123,2019-05-01,Ana
Harbour,04567,,
Airport,10001,2023-02-14,Raj
Output
CREATE TABLE `stores` (
  `store` VARCHAR(8),
  `zip` VARCHAR(5),
  `opened` DATE,
  `manager` VARCHAR(3)
);

INSERT INTO `stores` (`store`, `zip`, `opened`, `manager`) VALUES
  ('Downtown', '00123', '2019-05-01', 'Ana'),
  ('Harbour', '04567', NULL, NULL),
  ('Airport', '10001', '2023-02-14', 'Raj');
Open this example in the tool

Reserved words as headers in SQLite

Only INSERT statements are produced, and the reserved column names are double-quoted so SQLite accepts them.

Input
select,from,order
alpha,web,1
beta,mobile,2
Output
INSERT INTO "records" ("select", "from", "order") VALUES ('alpha', 'web', 1);
INSERT INTO "records" ("select", "from", "order") VALUES ('beta', 'mobile', 2);
Open this example in the tool

Common errors and how to fix them

ErrorCauseFix
This quoted field is never closed
Explained
A quote opens a field and never closes, which would swallow the rest of the file.Close the quote; write quotes inside values as two quotes.
There are no data rows, so no INSERT statements were writtenA warning: the CSV contains only a header row.Add data rows, or keep just the CREATE TABLE if that is all you need.
Row has 3 fields, expected 5; the missing fields are left empty
Explained
A warning: some rows are shorter than the header, so their missing values become NULL.Check that row for a missing comma or an accidental line break.
Duplicate header "total" renamed to "total_2"Two columns share a name, which a table definition cannot allow.Rename one of the headers in the CSV to something meaningful.

Frequently asked questions

Does the CSV need a header row?

Yes. The first row supplies the column names; if your file has none, add a header line before converting.

Why is my ZIP code column TEXT and not INTEGER?

Values with leading zeros are kept as text so 00123 is not stored as 123. Numeric columns are only chosen when every value is a plain number.

How are empty cells inserted?

As NULL. If you need empty strings instead, replace them after loading or edit the generated statements.

Can I load large files this way?

Thousands of rows are fine, especially with One multi-row INSERT. For millions of rows, a bulk loader such as COPY or LOAD DATA will be much faster.

Related tools