TSV to SQL
Generate INSERT statements from a TSV, with identifiers and string literals quoted for the dialect you pick. Values are batched into multi-row inserts rather than one statement per row, which is dramatically faster to execute and shorter to read. Column types for the optional CREATE TABLE are inferred from the data, conservatively.
How to use
- Paste or drop the TSV. The header row becomes the column names.
- Set the table name and pick your dialect — quoting rules differ (
"col"in Postgres,`col`in MySQL,[col]in SQL Server). - Tick CREATE TABLE to emit the DDL above the inserts.
- Review the types before running it. Inference is a starting point, not an authority.
When not to use INSERTs
For anything above a few thousand rows, the database's own bulk loader is far faster and doesn't build a giant SQL file: \copy t FROM 'f.tsv' WITH (FORMAT csv, DELIMITER E'\t', HEADER) in PostgreSQL, LOAD DATA INFILE in MySQL, .mode tabs then .import in SQLite. Generated inserts earn their place when you need the data in something — a migration file, a seed script, a test fixture, a bug report someone else can run.
If all you want is the schema, the schema generator produces the CREATE TABLE on its own, plus JSON Schema and a TypeScript interface.
Types, NULLs, and the leading-zero problem
A column is typed as an integer or numeric only if every non-empty value fits; one stray N/A makes it text. That conservatism is deliberate — a failed cast on row 40,000 is worse than a wide column. The case it gets wrong is the identifier that looks numeric: an account number stored as bigint loses its leading zeros permanently, so override the type by hand when the column is a label rather than a quantity.
Empty cells become NULL, not empty strings. TSV can't distinguish the two, and NULL is the more useful default for a load.
FAQ
Is the output safe against SQL injection?
String literals have their single quotes doubled, which is correct escaping for a literal — but this is generated SQL you're expected to read before running, not a substitute for parameterised queries in application code. Never build queries by concatenating user input, whatever this page produces.
Can it generate UPDATEs or upserts?
No — inserts only. An upsert needs to know the conflict key and the update policy, which is a decision rather than a transformation. Add ON CONFLICT (id) DO UPDATE SET … to the generated statements yourself.
How large are the batches?
500 rows per statement for most dialects, 1,000 for SQL Server. That stays under common statement-size limits while keeping the round trips low.
What about column names with spaces or capitals?
They're quoted for the dialect, so they work — but they'll need quoting in every query you write afterwards too. Header tools will snake_case them first.
Privacy
100% client-side. No upload. See the privacy policy.