ToolActToolAct

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

  1. Paste or enter CSV data in the input box, or upload a CSV file
  2. Set the table name (default is table_name)
  3. Select the appropriate delimiter (default is comma)
  4. Choose whether to use the first row as field names
  5. 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

Generate INSERT statements from a small CSV exportUpload a CSV, TSV, or text table, choose the delimiter, set the table name, and produce SQL INSERT statements using either header names or generated col1, col2, col3 columns. Parsing and statement generation both run in the browser, so the rows you import never leave the device until you paste them into psql, mysql, or your migration tool.
Match identifier quoting to the database styleSwitch between backticks for MySQL, double quotes for PostgreSQL/standard SQL, and single quotes for string literals, and optionally include a simple CREATE TABLE statement with VARCHAR(255) columns. Use it as a controlled intermediate step, then verify the SQL against the target database version before relying on it.
Prepare seed data while keeping SQL limits visibleThe tool escapes single quotes and doubles in values, supports four delimiters, and works well for demos, local fixtures, and admin repair drafts, but it does not infer data types, constraints, indexes, transactions, or database-specific bulk-load syntax like COPY, LOAD DATA, or multi-row VALUES batching.
Add IF NOT EXISTS guards when seeding shared databasesWrap the generated INSERT batch in a BEGIN/COMMIT transaction or pair it with a manual DELETE/INSERT pattern so re-running the seed does not duplicate rows in development and staging schemas. Because all parsing is local, you can iterate on the seed without re-uploading customer or staging data to an external service.
Tune VARCHAR(255) when real columns need TEXT or DECIMALThe CREATE TABLE draft uses VARCHAR(255) for every column, so adjust long descriptions to TEXT, monetary values to DECIMAL(p,s), and timestamps to TIMESTAMP in your migration before running the inserts in production. Review the generated column types against the real schema rather than applying the draft verbatim. Type inference here is purely lexical: a column of `1234` is treated as INT and `12.50` as DECIMAL only if a sample row already proves it, an empty cell becomes NULL rather than the empty string `''` (per SQL three-valued logic), and table-name sanitization strips spaces and punctuation but does not quote-reserve keywords such as `order` or `user` for MySQL. Most engines also benefit from batching inserts in groups of roughly 1000 rows per multi-row VALUES tuple to stay under their packet-size limit.

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.