CSV Schema GeneratorDetect Types, Get CREATE TABLE SQL

Drop in a CSV and get a data type for every column, a primary key suggestion, and ready-to-copy CREATE TABLE SQL, a TypeScript interface, or JSON Schema.

Your input is never sent anywhere.

Details

Everything runs in your browser. Your CSV is never sent to a server.

Drag and drop a CSV file here

or choose one from your computer

Turn a CSV into a draft table definition

Loading a CSV into a database starts with deciding what type each column should be. This tool reads every row of your file, picks a type for each column, and writes the table definition for you.

Columns are classified as integer, decimal, boolean, date, datetime, email, URL, enum, or text. A confidence percentage shows how many non-empty values matched the chosen pattern, so columns with mixed or messy data stand out. You can override any type from a dropdown, and the output updates right away.

The result comes out as CREATE TABLE for MySQL, PostgreSQL, and SQLite, a TypeScript interface, or a JSON Schema. Everything is computed in your browser, and the file is never uploaded.

Typical uses: import prep, prototypes, API types

Importing a file from a vendor or client

A partner sends a CSV export and you need a table to hold it. Get a first-draft CREATE TABLE instead of checking every column by hand.

Prototyping a schema from sample data

Start with a few hundred sample rows, generate the DDL, and use it as the starting point for your real schema.

Typing an API response or frontend model

Generate a TypeScript interface or a JSON Schema from the same CSV, so your frontend types and database columns start out in agreement.

Spotting messy columns before you load

Columns with empty cells are flagged as nullable, and a confidence below 100% means some values do not fit the detected type. Use that to decide which columns need cleanup first.

How to generate a CREATE TABLE statement from a CSV

  1. Drag a CSV or TSV file onto the upload area, or switch to Paste text, paste your data, and click Analyze CSV. Load sample CSV shows an example.
  2. Check the delimiter (auto-detect by default) and whether the first row is a header. Turn on snake_case if you want clean column names.
  3. Review each column's detected type, confidence, nullable flag, and sample values. Use the Change type dropdown to fix any wrong guess.
  4. Set a table name, pick MySQL, PostgreSQL, SQLite, TypeScript, or JSON Schema, then copy the result or download it as a file.

Note: Your CSV is read and analyzed in your browser. Nothing is sent to a server.

Limits to know before you run the SQL

  • Types are inferred from the values in this one file. Review the output before you run it against a real database.
  • VARCHAR(255), VARCHAR(2083), and DECIMAL(10,2) are fixed defaults. They are not sized from your longest string or your most decimal places.
  • Integer columns map to INT, or to BIGINT when any value is larger than 2,147,483,647 in absolute value.
  • Numbers with thousands separators or currency symbols, such as $1,234.50, are not recognized as numbers. Remove those characters first, or the column comes out as text.
  • Dates are matched by shape only, so 03/04/2025 is accepted whether it means March 4 or April 3. Convert dates to YYYY-MM-DD before loading.
  • Datetime columns map to DATETIME or TIMESTAMP, which carry no time zone. If your values end in Z or a UTC offset, adjust the type by hand.
  • Only PRIMARY KEY, NOT NULL, and MySQL ENUM are generated. Indexes, foreign keys, defaults, and CHECK constraints are up to you.

Detected column types and their SQL equivalents

What each type means in this tool and the SQL type it produces.

Detected typeDetection ruleMySQLPostgreSQLSQLite
BooleanEvery non-empty value is true/false, yes/no, or y/n (any case). Columns of 0 and 1 are read as integers.TINYINT(1)BOOLEANINTEGER
IntegerAt least 95% are whole numbers with no leading zero.INT (BIGINT above 2,147,483,647)INTEGER (BIGINT above 2,147,483,647)INTEGER
DecimalAt least 95% are integers or numbers with a decimal point, like 12.50.DECIMAL(10,2)NUMERIC(10,2)REAL
DatetimeAt least 90% match YYYY-MM-DD HH:MM[:SS] (also with T, fractional seconds, Z, or an offset), YYYY/M/D HH:MM, or M/D/YYYY h:mm with optional AM/PM.DATETIMETIMESTAMPTEXT
DateAt least 90% match YYYY-MM-DD, YYYY/M/D, or M/D/YYYY.DATEDATETEXT
EmailAt least 90% look like [email protected].VARCHAR(255)VARCHAR(255)TEXT
URLAt least 90% start with http:// or https://.VARCHAR(2083)TEXTTEXT
EnumAt most 8 distinct values, fewer than 60% of the non-empty values are distinct, and at least 4 non-empty values.ENUM('a','b',...)VARCHAR(255)TEXT
TextAnything that matched none of the above.VARCHAR(255)VARCHAR(255)TEXT
Checks run top to bottom, except that datetime is tested before date. The first one that passes wins.

Detection rules, thresholds, and edge cases

The details behind the type guesses, so you know when to trust them and when to override.

How each column is classified

For each column, empty cells are ignored and the remaining values are tested against the patterns in a fixed order. Integer and decimal pass at 95% matching values; datetime, date, email, and URL pass at 90%.
Values that do not match are not checked further. A column that is 96% integers and 4% words is still labeled integer, with a confidence of 96%.

What the confidence number tells you

Confidence is the share of non-empty values that matched the detected pattern. Boolean, enum, and text columns always show 100%, because they either match completely or are the fallback. A column with no values at all shows 0%.
Anything under 100% on a typed column means a few cells do not fit. Sort that column in a spreadsheet and look at the outliers before you load the file.

When a column becomes an enum

A column is suggested as an enum when it has 8 or fewer distinct values, those values are fewer than 60% of the non-empty cells, and there are at least 4 non-empty cells. Status, plan, and country-code columns usually qualify.
MySQL output uses ENUM with the values found in this file. PostgreSQL and SQLite output uses a plain text type, where you can add a CHECK constraint yourself.

ZIP codes, phone numbers, and other numeric-looking text

Whole numbers with a leading zero, like 02134, are treated as text so the zero is not lost. Phone numbers and account numbers without a leading zero still look like integers, and long ones push the column to BIGINT.
If you will never do math on a value, switch the column to Text with the Change type dropdown.

How the primary key suggestion works

A column is a candidate when it has no empty cells and no repeated values. Candidates named id, ending in _id, or named no are preferred. If none match, the first candidate in column order is used.
That can pick a column like email when it is the only unique one, so check that the suggestion is a real identifier.

Common mistakes with generated schemas

Running the generated VARCHAR(255) and DECIMAL(10,2) as they are

The lengths and precision are fixed defaults, not measured from your data. Longer text or values with more decimal places can fail to load or be cut off, depending on your database settings.

💡 See the solution▼
Check the longest string in each text column and the most decimal places in each decimal column, then adjust the generated types before you create the table.

Trusting a date column that mixes formats

2025-01-05 and 1/5/2025 in the same column both match a date pattern, so the column is detected as a date. The import then fails or misreads some rows, because the database expects one format.

💡 See the solution▼
Convert every date to YYYY-MM-DD in a spreadsheet or script before loading, and confirm whether your source uses month/day or day/month order.

Keeping the suggested primary key without checking it

A column that is unique and has no empty cells in this file is only unique in this file. A new export can repeat values, and a column like email can change over time.

💡 See the solution▼
Use the suggestion only if the column is a true identifier. Otherwise add an auto-increment or UUID column and make that the primary key.

Storing phone numbers or account numbers as integers

Identifiers without a leading zero are detected as integers. They then lose formatting later, and long values can overflow INT.

💡 See the solution▼
If you will never add or average the values, change the column to Text before copying the SQL.

Locking an enum to the values in one file

The ENUM list contains only the values found in this CSV. When a new status or plan shows up later, you have to alter the table before inserts will work.

💡 See the solution▼
If the set of values can grow, use VARCHAR with validation in your application, or a separate lookup table.

Questions about type detection and SQL output

Q.How does the tool decide a column's data type?

Q.

A. It ignores empty cells and checks the remaining values against a fixed list of patterns in this order: boolean, integer, decimal, datetime, date, email, URL, enum, then text. Integer and decimal need at least 95% of values to match. Datetime, date, email, and URL need at least 90%. Boolean needs every value to be true/false, yes/no, or y/n in any letter case. The first check that passes sets the type.

Q.Can I change a type the tool got wrong?

Q.

A. Yes. Every row in the results table has a Change type dropdown with all nine types. The SQL, TypeScript, and JSON Schema output updates as soon as you pick a different one, and that column's confidence shows 100%.

Q.What does the confidence percentage mean?

Q.

A. It is the share of non-empty values that matched the detected pattern. Boolean, enum, and text columns always show 100%, and a column with no values at all shows 0% as text. A number below 100% means some cells do not fit the type, so check those rows before you load the data.

Q.How is the primary key chosen?

Q.

A. A column qualifies when it has no empty cells and every value is distinct. If several columns qualify, the tool prefers one named id, ending in _id, or named no. Otherwise it takes the first qualifying column. Treat it as a suggestion: a column can be unique in one file without being a good key.

Q.Which databases and output formats are supported?

Q.

A. CREATE TABLE for MySQL, PostgreSQL, and SQLite, plus a TypeScript interface and a JSON Schema (draft-07). Types are mapped per database. For example, a boolean becomes TINYINT(1) in MySQL, BOOLEAN in PostgreSQL, and INTEGER in SQLite.

Q.Is my CSV uploaded anywhere?

Q.

A. No. Your browser reads the file, and JavaScript on the page parses it and builds the output. The contents are not sent to a server, so files with customer data stay on your device.

Q.How are column names with spaces or special characters handled?

Q.

A. Names that are not plain letters, digits, and underscores are quoted in the output: backticks for MySQL and SQLite, double quotes for PostgreSQL, and quoted keys in TypeScript. You can also turn on Convert column names to snake_case, which changes First Name to first_name. Duplicate names get a numeric suffix, and empty headers become column_1, column_2, and so on.

Q.Why does my ZIP code column show up as text?

Q.

A. Whole numbers with a leading zero, such as 02134, are not treated as integers, because converting them would drop the zero. If almost all values have no leading zero, the column can still come out as integer. In that case, switch it to Text with the dropdown.

Q.Which delimiters and CSV formats can it read?

Q.

A. Comma, tab, or semicolon. The default is auto-detect, which counts each one in the first line and picks the most frequent. Quoted fields can contain delimiters, line breaks, and doubled quotes, and a UTF-8 byte order mark at the start of the file is removed.

Q.How does it decide between NULL and NOT NULL?

Q.

A. A column with at least one empty or whitespace-only cell stays nullable. A column with no empty cells gets NOT NULL, except the primary key, which gets PRIMARY KEY only.

Q.Does it create INSERT statements or load my data?

Q.

A. No. It generates the table definition only. After you create the table, use your database's import tool, such as LOAD DATA in MySQL, COPY in PostgreSQL, or .import in the SQLite shell.

Q.Can I use an Excel file?

Q.

A. Not directly. The tool reads CSV and TSV text. In Excel, choose Save As and pick CSV UTF-8, then upload that file.

User Feedback & Request

Your feedback
makes this tool better.

Tell us which features you'd like, what should be fixed, or which new tool you'd like to see. An engineer reads every submission and uses it to guide development.

Send feedback