CSV to SQL Converter
Upload CSV file or paste data to convert to SQL INSERT statements
Drop CSV file here or click to select file
What is CSV to SQL?
CSV to SQL is an online data format conversion tool that converts CSV (Comma-Separated Values) format data into SQL INSERT statements for easy database import.
CSV is a common tabular data format widely used for spreadsheets and data export. SQL is the standard query language for relational databases, and INSERT statements are used to insert data into database tables.
With this tool, you can quickly convert CSV data into executable SQL statements, supporting custom table names, field names, and quote styles for convenient data migration and import operations.
For production data or codebases, the result should still be checked with a parser, tests, or the project rules.
How to Use
How to use
- Paste or enter CSV data in the input box, or upload a CSV file
- Set the table name (default is table_name)
- Select the appropriate delimiter (default is comma)
- Choose whether to use the first row as field names
- SQL INSERT statements will be generated on the right
Import Safety
- Review generated INSERT statements for table name, column order, escaping, NULL values, and numeric formats before execution.
- Run a small batch first and wrap real imports in a transaction when your database supports it.
Use Cases
Technical Principle
CSV input is parsed with an RFC 4180-compliant state machine (handling quoted fields, escaped doubled quotes, and CRLF/LF line endings), then emitted as ANSI SQL INSERT statements. The two grammars do not overlap: CSV uses double-quote-doubling for escapes ("O""Brien"), while SQL uses single-quote-doubling inside string literals ('O''Brien') per ISO/IEC 9075. The converter rewrites every internal apostrophe to a doubled pair before wrapping the value in single quotes, which is the only escaping mechanism guaranteed across MySQL, PostgreSQL, SQLite, SQL Server, and Oracle. Identifier quoting is dialect-specific: MySQL uses backticks `users`, PostgreSQL and SQL Server use double quotes "users" (case-sensitive when quoted), and SQLite accepts both - choose the style that matches the target engine to avoid "unknown column" errors caused by case folding. Type inference is intentionally minimal because CSV has no type metadata. The optional CREATE TABLE draft emits VARCHAR(255) for every column - safe but suboptimal - and leaves it to the user to substitute INT, BIGINT, DECIMAL(p,s), DATE, TIMESTAMP, or TEXT before running against production. Empty cells are emitted as NULL (the SQL three-valued-logic absence marker) rather than as the empty string '', because most spreadsheet exports use a blank field to represent missing data; if the empty-string distinction matters, switch to a typed loader instead. Reserved words such as user, order, and group are NOT auto-quoted, so a column literally named order will fail to parse on MySQL unless the user wraps it in backticks manually. For large imports, single-row INSERT statements are correct but slow: MySQL's default max_allowed_packet is 64 MB and a multi-row INSERT INTO t VALUES (...), (...), (...) in batches of ~1000 rows per statement is typically 5-10x faster than one statement per row because of network round-trip and parsing overhead. Wrapping the batch in BEGIN; ... COMMIT; lets the database stage the inserts and commit them atomically, which is essential when a partial insert would leave a foreign-key relationship inconsistent. Note that this tool does not infer foreign keys, indexes, primary key constraints, or AUTO_INCREMENT - it only converts row data, so the receiving schema must already exist or the CREATE TABLE draft must be edited before execution. For bulk loads of millions of rows, prefer database-native syntax: PostgreSQL COPY FROM, MySQL LOAD DATA INFILE, or SQL Server bcp.
- SQL string literal escaping per ISO/IEC 9075: single quotes are doubled ('O''Brien'), not backslash-escaped.
- Identifier quoting differs: ` for MySQL, " for PostgreSQL/SQL Server, both accepted in SQLite.
- Empty CSV cell -> SQL NULL (three-valued logic), not '' - the empty-string distinction is lost.
- Reserved words (order, user, group) are not auto-quoted; manual escaping required.
- Multi-row INSERT batches of ~1000 rows hit ~5-10x throughput vs. single-row statements (MySQL max_allowed_packet 64 MB default).
- Wrap with BEGIN; ... COMMIT; for atomic seed inserts; partial failures rollback cleanly.
- Bulk loads over 1M rows: prefer PostgreSQL COPY, MySQL LOAD DATA INFILE, SQL Server bcp over generated INSERTs.
Examples
Basic CSV -> INSERT statements (MySQL backtick)
CSV:
id,name,email
1,Alice,alice@example.com
2,Bob,bob@example.com
SQL:
INSERT INTO `users` (`id`, `name`, `email`) VALUES (1, 'Alice', 'alice@example.com');
INSERT INTO `users` (`id`, `name`, `email`) VALUES (2, 'Bob', 'bob@example.com');With CREATE TABLE (PostgreSQL double-quote style)
CSV:
product_id,price,in_stock
101,29.99,true
102,15.50,false
SQL:
CREATE TABLE "products" (
"product_id" VARCHAR(255),
"price" VARCHAR(255),
"in_stock" VARCHAR(255)
);
INSERT INTO "products" ("product_id", "price", "in_stock") VALUES ('101', '29.99', 'true');
INSERT INTO "products" ("product_id", "price", "in_stock") VALUES ('102', '15.50', 'false');
-- Tip: change VARCHAR(255) to INT / DECIMAL(10,2) / BOOLEAN before running in production.Escaping single quotes inside values
CSV:
id,note
1,O'Brien signed off
2,It's already done
SQL:
INSERT INTO `notes` (`id`, `note`) VALUES (1, 'O''Brien signed off');
INSERT INTO `notes` (`id`, `note`) VALUES (2, 'It''s already done');
Note: single quotes are doubled (''), which is SQL-standard escaping.Type inference - INT vs DECIMAL vs TEXT
CSV:
user_id,score,bio
1,100,Hello
2,87.5,Long bio text...
Detected types (heuristic):
user_id -> INT
score -> DECIMAL(10,2)
bio -> VARCHAR(255) (consider TEXT for longer content)
SQL preview:
INSERT INTO `students` (`user_id`, `score`, `bio`) VALUES (1, 100, 'Hello');
INSERT INTO `students` (`user_id`, `score`, `bio`) VALUES (2, 87.5, 'Long bio text...');FAQ
What kind of SQL does the tool generate?
It produces standard CREATE TABLE plus INSERT INTO statements. The dialect is portable SQL by default - works on MySQL, PostgreSQL, SQLite, MSSQL with minor type adjustments. Some pages let you pick a target dialect for the data types (VARCHAR vs TEXT, INT vs INTEGER, etc.).
How are column names derived?
From the first row of the CSV when 'first row is header' is enabled. The page sanitises names by replacing spaces with underscores and quoting reserved words. With headers disabled, columns become col_1, col_2, etc.
How is the data type for each column inferred?
The page samples values and picks the narrowest type that fits: INTEGER if every cell is a whole number, DECIMAL if some are fractional, VARCHAR(N) sized to the longest cell, BOOLEAN for true/false, DATE/DATETIME for ISO-format strings. You can override the inferred type before generating the SQL.
What about quotes and special characters in the data?
Single quotes inside string values are escaped by doubling them (O'Brien → 'O''Brien'). Backslashes and Unicode characters are passed through literally - this matches PostgreSQL's standard_conforming_strings = on behaviour. Verify the result against MySQL's NO_BACKSLASH_ESCAPES mode if you target MySQL.
Why are NULLs different from empty strings?
An empty CSV cell (e.g. 'a,,c') becomes SQL NULL; a quoted empty string ('a,"",c') becomes ''. The page follows that convention. Toggle 'treat empty as NULL' off if you need empty strings preserved for both cases.
Is my data uploaded?
No. CSV is parsed and SQL is generated in your browser. Inputs and outputs never leave the page. Use the result as a SQL script that you import into your database server yourself.
Should I use the generated SQL on a production database?
Review it first. The CREATE TABLE statement may not match your existing schema; the INSERTs do not include constraints, foreign keys, or indexes. Use it as a starter you can edit, especially for primary keys, NOT NULL constraints, and proper data types.