Opsdeck ER Diagram from SQL DDL (SVG, Mermaid)
Turn CREATE TABLE statements into an ER diagram with crow’s foot notation (SVG, Mermaid).
Try an example: Shop schema (PostgreSQL) · Blog with tags and threaded comments (MySQL, force layout)
How it works
Paste PostgreSQL, MySQL or SQLite DDL and get an entity-relationship diagram as SVG: tables with their columns and types, primary, foreign and unique keys, and relationships drawn in crow’s foot notation (one, zero-or-one, zero-or-many). Layered layout along foreign keys or a force-directed layout with a fixed seed, plus a Mermaid erDiagram and a text list of relationships. It is the diagram of the Opsdeck Database desk.
- The DDL is read into the same schema model as the Opsdeck schema diff (columns, keys, foreign keys, checks, indexes; ALTER TABLE applied in order).
- Layered layout: tables get a rank by the longest chain of foreign keys that point to them (referenced tables left, referencing tables right; cycles are broken at the edge that closes them); four barycentre sweeps order the tables inside each column to reduce crossings.
- Force-directed layout: Fruchterman–Reingold with a gravity term and a seeded random start (mulberry32), followed by overlap removal; the same seed gives the same diagram everywhere.
- Crow’s foot notation: the referencing side is zero-or-many (zero-or-one when the foreign-key columns are also unique); the referenced side is exactly one when the foreign-key columns are NOT NULL, otherwise zero-or-one.
Sources
- Gordon Everest: Basic data structure models explained with a common example (1976), origin of crow’s foot notation (Proc. Fifth Texas Conference on Computing Systems)
- Fruchterman & Reingold: Graph drawing by force-directed placement (1991) (Software: Practice and Experience 21(11))
- Mermaid entity relationship diagrams (Mermaid)
Part of Opsdeck
-
Opsdeck Developer & ops workbench
One deck for CI failures, cron, traces, k8s events, API diffs, query plans and Terraform.
Related tools
- Opsdeck Schema Diff & Migration Generator (PostgreSQL, MySQL, SQLite) – Compare two DDL versions: ordered migration, rollback script and data-loss warnings.
- Opsdeck Normalization Checker (keys, minimal cover, 2NF/3NF/BCNF, decomposition) – Candidate keys, minimal cover, 2NF/3NF/BCNF and lossless decompositions from FDs.
- Diagram & Flowchart Maker – Write flowcharts, sequence diagrams and mind maps as text and get a laid-out SVG/PNG diagram.
- Data Lineage Explorer – Paste SQL or dbt models: table lineage graph, column lineage and upstream/downstream of any field.
How to use the Opsdeck ER Diagram from SQL DDL
Paste CREATE TABLE statements and get an entity-relationship diagram in crow's foot notation as SVG, plus a Mermaid version and a list of relationships.
What it is for
An ER diagram is the quickest way to explain a schema in a design review, an onboarding document or a ticket. Drawing one by hand goes stale the day after the next migration. This tool draws it from the DDL itself: paste the CREATE TABLE, CREATE INDEX and ALTER TABLE statements of PostgreSQL, MySQL or SQLite and you get an SVG with every table, its columns and types, the keys and the relationships.
It shows what the DDL declares. Relationships that exist only in your application code, without a foreign key, are not drawn.
Worked example
The first example uses the version-2 shop schema in PostgreSQL: customers, products, orders and order_items. The tool answers 4 tables and 3 relationships drawn as an ER diagram (layered layout).
In the layered layout, customers and products stand on the left because nothing they reference comes before them, orders sits in the middle and order_items on the right. The tables list shows order_items with the composite primary key order_id, sku, two foreign keys and one check.
All three relationships read "exactly one" on the referenced side because the foreign-key columns are NOT NULL: "each orders row belongs to exactly one customers row; each customers row has any number of orders rows". In the blog example (MySQL, force-directed layout, seed 7), comments.parent_id may be NULL, so that relationship shows a circle for "at most one" parent.
How to read the result
- Table boxes: blue header with the table name; each row shows PK (primary key), FK (foreign key) or UQ (single-column unique key), the column name and the type. A
!after the type means NOT NULL. - Lines: the crow's foot sits at the referencing table (many rows); a bar at the referenced table means exactly one, a circle means optional. When the foreign-key columns are also unique, the many side becomes "at most one", a one-to-one relationship.
- Relationships table: the same information as sentences, useful as a text alternative and for screen readers.
- Mermaid erDiagram: paste it into Markdown that renders Mermaid, for example a README or a wiki page.
- Download: the SVG scales without blur and opens in any browser or vector editor.
Tips and common mistakes
- Long tables are cut after 40 columns with a "… more columns" line; the column count in the tables list stays exact.
- If the layered layout gets crowded, switch to force-directed and try a few seeds. The same seed always gives the same picture, so you can name it in a ticket.
- Untick "Show column types" for a compact overview diagram for slides.
- Self-references such as
employees.manager_idare drawn as a loop on the right side of the box. - A warning like "references table … which is not defined" means a table is missing from what you pasted; the line is then not drawn.
FAQ
Which notation does the diagram use?
Crow's foot (information engineering) notation: a three-pronged foot for "many", a bar for "one" and a circle for "zero/optional".
Can I edit the layout by dragging tables?
No. The layout is computed so that it is reproducible: layered by foreign-key depth, or force-directed with a fixed seed.
Why does a one-to-one relationship show "at most one" instead of "exactly one"?
A unique foreign key allows each referenced row to have at most one referencing row, but nothing forces it to have one, so the referenced side keeps the circle.
Does it read views or partitioned tables?
Views, triggers and functions are skipped with a note. Partitions are not modelled; draw the parent table.
Guide last updated:
For scripts and AI agents
- JSON API:
POST https://opsdeckerdiagram.usefulweb.app/api/v1/calculate(same calculation as this page) - Interface description: OpenAPI 3.1 · AI guide: llms.txt
- MCP server (Streamable HTTP):
https://opsdeckerdiagram.usefulweb.app/mcp· tool nameopsdeck_er_diagram
Example request
curl -s -X POST https://opsdeckerdiagram.usefulweb.app/api/v1/calculate \
-H 'content-type: application/json' \
-d '{…see OpenAPI examples…}'