How to make an ER diagram from SQL, without a database
Paste your CREATE TABLE statements into the SQL to ER Diagram Generator and you get an SVG of the tables with their foreign keys drawn between them. No database connection, no credentials, no upload — the SQL is parsed in the page. This is what it reads, and what it does not.
SQL to ER Diagram Generator
100% In-browser execution. Zero server uploads, instant results, free forever.
Paste the schema, get the diagram
Open the SQL to ER Diagram Generator and paste SQL like this:
```sql CREATE TABLE users ( id INTEGER PRIMARY KEY, email VARCHAR(255) UNIQUE );
CREATE TABLE orders ( id INTEGER PRIMARY KEY, user_id INTEGER NOT NULL REFERENCES users(id), total DECIMAL(10, 2) ); ```
You get an SVG with two table cards, id marked PK in each, user_id marked FK, and a line joining it to users.id.
There is no connection string and no account. The SQL is text, and reading text does not require a database — which is the whole reason this can happen in a browser tab at all.
What it reads, exactly
Every item here was checked by running the parser against the real output of the tool named, not against simplified examples.
Table definitions
CREATE TABLEandCREATE TABLE IF NOT EXISTS- Names quoted with double quotes or backticks
- Schema-qualified names —
CREATE TABLE public.users, which is howpg_dumpwrites every table. The schema is dropped from the label. - Trailing table options —
) ENGINE=InnoDB DEFAULT CHARSET=utf8;, which is howmysqldumpcloses every table.
Keys and relationships
- Inline:
user_id INTEGER REFERENCES users(id) - Table-level:
FOREIGN KEY (user_id) REFERENCES users(id) - Declared afterwards:
ALTER TABLE ONLY orders ADD CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(id);—pg_dumpputs foreign keys here rather than insideCREATE TABLE, often hundreds of lines further down the file. - Composite primary keys:
PRIMARY KEY (order_id, sku)marks both columns. NOT NULL, used to decide whether a column is shown as nullable.
Commas inside parentheses are left alone, so DECIMAL(10, 2) stays one type rather than becoming two columns.
What it does not do
A diagram that is wrong in a way you cannot see is worse than one that refuses to draw, so here is the boundary.
- It does not connect to anything. If your schema only exists in a running database, you need to export it first —
mysqldump --no-dataorpg_dump --schema-onlyboth produce exactly the text this reads. - It does not infer relationships that are not declared. A column called
user_idwith noREFERENCESand no foreign key constraint is drawn as an ordinary column, because guessing from a name is how diagrams acquire relationships that do not exist in the database. - It does not read views, triggers, stored procedures or indexes. Tables and the keys between them only.
- It does not show cardinality. A foreign key is drawn as a line. Whether that relationship is one-to-many or one-to-one is not something
REFERENCEStells you. - It does not parse dialect-specific column syntax beyond the name and type. Postgres arrays, MySQL generated columns and similar are read as a type string and drawn as written.
Why this one runs in the page
A schema is a map of a business. Table and column names carry customer structure, pricing models, internal identifiers, and often the names of clients. Handing that to a web service to draw a picture is a larger disclosure than it looks, and for anyone working under an NDA or on a client system it is usually one they have not been given permission to make.
The tool is served with connect-src 'none', a Content-Security-Policy directive that tells the browser to refuse every outbound network request the page attempts. It is not a promise in a privacy policy; it is enforced by the browser, and you can check it yourself: open the network tab, paste a schema, generate a diagram, and watch nothing leave. Turning off your network connection entirely also works — the tool keeps running.
Getting the diagram out
The output is an SVG, which matters more than it sounds. It is text, so it goes into a repository and diffs like code; it scales to any size without blurring, so it survives being dropped into documentation or printed at A3 for a wall; and it can be opened by any browser with no software installed.
Three themes: dark, light, and a navy-and-cyan blueprint. The dark one suits a README rendered on GitHub; the light one prints without emptying a cartridge.
Inferring Relationships When the Schema Does Not Declare Them
A diagram generator reads FOREIGN KEY constraints and draws the edges they describe. The difficulty is that a large proportion of real schemas do not declare them.
Foreign keys are frequently absent for reasons that seemed sound at the time: MySQL's MyISAM engine never supported them; ORMs such as older Rails and Django configurations manage referential integrity in application code; sharded and distributed databases often cannot enforce cross-shard constraints; and teams disable them for bulk-load performance and never restore them.
When constraints are missing, relationships must be inferred from naming, and a small set of conventions covers most schemas:
- `<table>_id` or `<table>Id` referencing the singular or plural form of a table name —
user_idtousers. - `fk_<table>` prefixes from schemas generated by older tools.
- Exact column-name matches where a non-primary-key column shares a name with another table's primary key.
Inference is a heuristic and should be shown as one. A diagram that draws a dashed edge labelled "inferred" is honest; one that draws inferred and declared relationships identically tells the reader something the schema does not say. The distinction matters when the diagram is being used to plan a migration, where a relationship the database does not actually enforce behaves very differently from one it does.
Reading Cardinality From the Constraints
Cardinality — one-to-one, one-to-many, many-to-many — is not stated directly in DDL. It is deduced from which columns carry which constraints.
One-to-many is the default case: a foreign key column on the child table, not unique. Many orders rows may carry the same customer_id.
One-to-one is a foreign key that also carries a UNIQUE constraint, or one that is itself the primary key. user_profiles.user_id as both primary key and foreign key expresses exactly one profile per user.
Many-to-many is never a single relationship. It is a junction table whose primary key is a composite of two foreign keys:
CREATE TABLE course_enrolments (
student_id INT NOT NULL REFERENCES students(id),
course_id INT NOT NULL REFERENCES courses(id),
enrolled_on DATE NOT NULL,
PRIMARY KEY (student_id, course_id)
);
A good diagram recognises that pattern and can collapse it into a single many-to-many edge, while still showing that the junction table carries its own attribute — enrolled_on here — because a junction table with extra columns is a real entity rather than pure plumbing.
Optionality comes from nullability. A nullable foreign key means the relationship is optional; NOT NULL makes it mandatory. Notation conventions differ, but crow's foot marks this distinction with a circle for optional and a bar for mandatory, and it changes how a reader understands the model.
Frequently Asked Questions (FAQ)
Do I need to give it database access or a connection string?
No. It reads SQL text — the CREATE TABLE statements themselves. There is no field for a host, a user or a password, because nothing connects to anything.
Will it read a mysqldump or pg_dump file?
Yes. Both were broken until 2026-09-20 and both are covered now: mysqldump closes tables with ENGINE options, and pg_dump qualifies names with a schema and declares foreign keys in separate ALTER TABLE statements. Export with `mysqldump --no-data` or `pg_dump --schema-only` and paste the result.
Does my schema get uploaded?
No. The page is served with `connect-src 'none'`, which makes the browser refuse any outbound request the page tries to make. You can verify it in the network tab, or by disconnecting from the internet and using the tool anyway.
Why is my foreign key missing from the diagram?
Almost always because it is not declared in the SQL. A column named user_id is only drawn as a relationship if the schema says REFERENCES or FOREIGN KEY somewhere — including in a later ALTER TABLE. The tool does not guess relationships from column names, because a guessed relationship looks exactly like a real one.
Can it show one-to-many versus one-to-one?
No. A foreign key is drawn as a line between the two columns. SQL does not record cardinality in the constraint, so showing it would mean inventing it.
How are ER diagrams generated when a schema has no foreign keys?
By inferring relationships from naming conventions, most commonly a column named user_id matching a table named users, fk_ prefixes from older generators, and exact matches between a non-key column and another table primary key. Missing foreign keys are common because MyISAM never supported them, many ORMs enforce integrity in application code, and sharded databases often cannot. Inferred edges should be drawn distinctly from declared ones.
How is cardinality determined from SQL DDL?
From the constraints rather than stated directly. A plain foreign key on a child table gives one-to-many. A foreign key that also carries a UNIQUE constraint, or that is itself the primary key, gives one-to-one. Many-to-many is expressed as a junction table whose primary key is a composite of two foreign keys. Nullability gives optionality, since a nullable foreign key makes the relationship optional.
Should a junction table appear in an ER diagram?
It depends on whether it carries its own attributes. A pure junction table with nothing but two foreign keys can be collapsed into a single many-to-many edge. One with additional columns, such as an enrolment date, is a real entity in its own right and should be shown as one, because those attributes belong to the relationship rather than to either side.
Related Guides & Solutions
JSON to Zod Schema, Generated in Your Browser
Clean Messy CSV and Convert It to JSON
Convert Unix Epoch Timestamps to UTC and Local
Generate RFC 4122 UUID v4s on Your Own Device
Ready to use SQL to ER Diagram Generator?
Execute this workflow privately on your device right now without creating an account or paying for cloud API credits.