How to use the sql create table generator
- Enter the table name at the top, for example
usersorshop.orders. - List columns in the text area, one per line: the column name, a data type and optional constraints such as
NOT NULL,DEFAULT ...,PRIMARY KEY,UNIQUEorCHECK (...). Add table-level lines such asPRIMARY KEY (a, b)if you need them. - Choose the SQL dialect from the dropdown. Common types are mapped to the target database (for example
SERIALbecomesINT IDENTITY(1,1)in SQL Server) and identifiers are quoted with the dialect's characters. A note under the result lists every type that was changed. - Toggle options:
IF NOT EXISTSadds the guard where the database supports it;Include column commentsturns the text after--on a column line into a column comment. - Copy the statement and review it before running it, because type mappings are close equivalents, not exact ones.
How the generator works
This sql create table generator reads each non-empty line as a column: a name (bare or quoted with double quotes, backticks or brackets), a type with optional length, precision or [] array suffix, and everything after that as constraints, which are kept as written. A trailing -- comment is split off and used as the column comment. Lines that start with PRIMARY KEY (, UNIQUE (, FOREIGN KEY (, CHECK ( or CONSTRAINT name are treated as table constraints and placed after the columns.
It is not a full SQL parser. The type is translated to the chosen dialect, the identifiers are re-quoted, and the constraint text is passed through with a few safe rewrites: AUTO_INCREMENT, AUTOINCREMENT and IDENTITY become the dialect's form, DEFAULT TRUE and DEFAULT FALSE become 1 and 0 for SQL Server and Oracle, and NOW() becomes CURRENT_TIMESTAMP for SQLite, SQL Server and Oracle. Text inside quotes is never changed.
Dialect type mapping reference
The table shows how common input types are translated. Types not listed pass through unchanged. A note under the output names every type that was changed.
| Input | PostgreSQL | MySQL | SQLite | SQL Server | Oracle |
|---|---|---|---|---|---|
SERIAL / BIGSERIAL | same | INT / BIGINT AUTO_INCREMENT | INTEGER plus PRIMARY KEY AUTOINCREMENT | INT / BIGINT IDENTITY(1,1) | NUMBER(10) / NUMBER(19) GENERATED BY DEFAULT AS IDENTITY |
INT, INTEGER, BIGINT, TINYINT | INTEGER, BIGINT; TINYINT becomes SMALLINT | same | INTEGER | same (INTEGER becomes INT) | BIGINT becomes NUMBER(19), TINYINT becomes NUMBER(3) |
VARCHAR(n) | same | same | same | same | VARCHAR2(n) |
TEXT | TEXT | TEXT | TEXT | VARCHAR(MAX) | CLOB |
BOOLEAN / BOOL | BOOLEAN | BOOLEAN | BOOLEAN | BIT | NUMBER(1) |
JSON / JSONB | same | JSON | TEXT | NVARCHAR(MAX) | CLOB |
TIMESTAMP | TIMESTAMP | TIMESTAMP | TIMESTAMP | DATETIME2 | TIMESTAMP |
DATETIME | TIMESTAMP | DATETIME | DATETIME | DATETIME2 | TIMESTAMP |
TIMESTAMPTZ | same | DATETIME | same | DATETIMEOFFSET | TIMESTAMP WITH TIME ZONE |
DECIMAL(p,s) / NUMERIC(p,s) | same | same | same | same | NUMBER(p,s) |
DOUBLE | DOUBLE PRECISION | DOUBLE | DOUBLE | FLOAT | DOUBLE PRECISION |
UUID | UUID | CHAR(36) | TEXT | UNIQUEIDENTIFIER | RAW(16) |
BLOB / BYTEA | BYTEA | BLOB | BLOB | VARBINARY(MAX) | BLOB |
TEXT[] (array) | same | JSON | TEXT | NVARCHAR(MAX) | CLOB |
SQLite stores values by affinity, so its declared type names are mostly labels. Where the target has no equivalent (arrays outside PostgreSQL, time zone types in MySQL), the value has to be stored as JSON text or converted by your application.
Identifier quoting rules
Each dialect uses a different quoting character:
- PostgreSQL, Oracle, SQLite: double quotes
"identifier" - MySQL: backticks
`identifier` - SQL Server: brackets
[identifier]
The generator quotes a name only when it contains characters outside A-Z a-z 0-9 _, starts with a digit, or is a common SQL reserved word such as order, user or group. Names you already quoted in the input are re-quoted for the chosen dialect. Quoted names keep their exact case, and in PostgreSQL and Oracle you must then quote them the same way in every query.
Constraints and defaults
The sql create table generator passes column constraints through as written: NOT NULL, DEFAULT value, PRIMARY KEY, UNIQUE, CHECK (expression) and REFERENCES table(col). Table-level lines such as PRIMARY KEY (a, b), UNIQUE (email), FOREIGN KEY (user_id) REFERENCES users(id) and CONSTRAINT name CHECK (...) are placed after the columns.
MySQL parses but ignores an inline REFERENCES on a column, so for MySQL the generator moves it into a table-level FOREIGN KEY. Default expressions are otherwise kept as written, so check functions such as CURRENT_TIMESTAMP or uuid_generate_v4() exist in your database.
Common mistakes
- Missing table name - the generator returns an error; every statement needs a table.
- A column with no type - a line with only a name is reported with its line number.
- Using dialect-specific types in another dialect - the table above covers common types, but exotic ones (PostgreSQL
TSVECTOR, OracleXMLTYPE) pass through unchanged and will fail elsewhere. - Adding your own commas - not needed; the generator adds the separators and removes a trailing comma if you pasted one.
- Two auto-increment keys in SQLite - a table can have only one
PRIMARY KEY AUTOINCREMENTcolumn, so only the firstSERIALcolumn gets it.
When to use a full schema tool
This generator is meant for quick tables, prototypes and learning. For production schema changes use a migration tool (Flyway, Liquibase, Alembic, Prisma Migrate) that tracks versions and supports rollbacks. The SQL Formatter can tidy the resulting statement.
Worked examples
| Example | Input | Result |
|---|---|---|
| Basic users table | Table name: users; Column definitions (one per line): id INTEGER PRIMARY KEY / name VARCHAR(100) NOT NULL / email VARCHAR(255) UNIQUE / created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP; SQL dialect: postgresql; Add IF NOT EXISTS: yes; Include column comments: no | CREATE TABLE IF NOT EXISTS users ( / id INTEGER PRIMARY KEY, / name VARCHAR(100) NOT NULL, / email VARCHAR(255) UNIQUE, / created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP / ); |
| E-commerce products (MySQL) | Table name: products; Column definitions (one per line): sku VARCHAR(32) PRIMARY KEY / title VARCHAR(200) NOT NULL / price DECIMAL(12,2) NOT NULL CHECK (price >= 0) / stock INT DEFAULT 0 / category_id INT / created_at DATETIME DEFAULT CURRENT_TIMESTAMP; SQL dialect: mysql; Add IF NOT EXISTS: yes; Include column comments: yes | CREATE TABLE IF NOT EXISTS products ( / sku VARCHAR(32) PRIMARY KEY, / title VARCHAR(200) NOT NULL, / price DECIMAL(12,2) NOT NULL CHECK (price >= 0), / stock INT DEFAULT 0, / category_id INT, / created_at DATETIME DEFAULT CURRENT_TIMESTAMP / ); |
| Event log (SQLite) | Table name: events; Column definitions (one per line): id INTEGER PRIMARY KEY AUTOINCREMENT / type TEXT NOT NULL / payload JSON / occurred_at TEXT DEFAULT (datetime('now')); SQL dialect: sqlite; Add IF NOT EXISTS: no; Include column comments: no | CREATE TABLE events ( / id INTEGER PRIMARY KEY AUTOINCREMENT, / type TEXT NOT NULL, / payload TEXT, / occurred_at TEXT DEFAULT (datetime('now')) / ); |
FAQ
Does this tool support composite primary keys or table-level foreign keys?
Yes. Write them as their own lines, for example PRIMARY KEY (order_id, line_no) or FOREIGN KEY (user_id) REFERENCES users(id), and they are placed after the columns.
Can I paste an existing CREATE TABLE statement and convert it to another dialect?
Not directly. The tool expects a simple column list. For dialect conversion of full statements, use the SQL Formatter together with manual type adjustments.
Why does my generated statement have double quotes around every identifier in PostgreSQL?
The generator quotes identifiers that are reserved words, contain special characters or start with a digit. If you prefer lower-case unquoted names, write them in lower case without spaces.
Are the type mappings exact equivalents?
No, they are close approximations. For example, PostgreSQL SERIAL creates a sequence, while MySQL AUTO_INCREMENT is a column attribute, and an Oracle NUMBER(1) has no true/false type. A note under the result lists each change so you can review it, and you should check the target database documentation for exact behaviour.
Does the tool run in the browser or on a server?
It runs entirely in your browser. No SQL is sent anywhere.
Can I generate multiple tables at once?
One table per generation. Run the tool again for each table.
Does IF NOT EXISTS work in every dialect?
PostgreSQL, MySQL and SQLite support it directly. SQL Server has no such clause for CREATE TABLE, so the generator wraps the statement in an IF OBJECT_ID(...) IS NULL check. Oracle supports it only from version 23ai, so it is left out and the note says so.
How are column comments written?
Put the text after -- on the column line and tick the comments option. PostgreSQL and Oracle get COMMENT ON COLUMN statements, MySQL gets an inline COMMENT '...', SQL Server gets sp_addextendedproperty calls, and SQLite keeps it as a SQL comment because it has no column comments.