Convert Mermaid ER to PostgreSQL

Generate production-ready PostgreSQL SQL code from your Mermaid ER diagrams in seconds.

postgres
Dialect: postgresTables: 2
Done.
mermaid
Live preview mermaid

How the Mermaid ER to PostgreSQL conversion works

Mermaid erDiagram is a Markdown-friendly notation rendered natively by GitHub, GitLab, Notion, and Obsidian — which makes it the most common way to keep an ER diagram next to the code it describes.

Entities are blocks of `type name marker` lines (markers: PK, FK, UK, INDEX), and relationships use cardinality arrows like `USER ||--o{ POST : writes` — one-to-many from USER to POST. The converter reads both, plus comment directives for everything the base syntax can't express.

Paste your Mermaid ER source into the editor above and the engine parses it into an intermediate schema — tables, columns, relationships, indexes — then generates PostgreSQL DDL from that model. Anything the diagram syntax can't express (NOT NULL, defaults, enums, CHECK constraints, composite indexes) you add with comment directives like %% ::NN, ::DEFAULT(now()) on the line above a column. The Mermaid ER reference documents the full vocabulary.

What the generator emits for PostgreSQL

  • CREATE TABLE statements with double-quoted identifiers
  • SERIAL primary keys for single integer PK columns
  • CREATE TYPE … AS ENUM for ::ENUM(...) columns
  • ALTER TABLE … ADD CONSTRAINT foreign keys with ON DELETE / ON UPDATE actions
  • CREATE INDEX / CREATE UNIQUE INDEX, including partial indexes with a WHERE clause
  • COMMENT ON TABLE and COMMENT ON COLUMN for documentation carried over from the diagram

Type mapping: Mermaid ER to PostgreSQL

Diagram column types are logical — the generator maps each one to the idiomatic PostgreSQL type. These are the exact mappings the engine uses:

Diagram typePostgreSQL typeNotes
intINTEGERSERIAL when it is the auto-increment primary key
stringTEXTuse varchar(n) in the diagram for VARCHAR(n)
textTEXT
decimalNUMERICdecimal(10,2) passes precision through
booleanBOOLEAN
dateDATE
timestampTIMESTAMPTZtimezone-aware by default
uuidUUIDnative PostgreSQL UUID type
bigintBIGINT
blobBYTEA

Keys, relationships, and enums

A single `int id PK` column becomes `"id" SERIAL PRIMARY KEY`. Composite primary keys (e.g. on junction tables) emit a table-level `PRIMARY KEY (a, b)` clause without auto-increment.

Relationships emit `ALTER TABLE … ADD CONSTRAINT fk_<table>_<column> FOREIGN KEY … REFERENCES …` after all tables are created, so declaration order never matters. `::RELATIONSHIP[onDelete: CASCADE]` adds the corresponding ON DELETE action.

PostgreSQL gets a real enum: `::ENUM(active, inactive)` emits `CREATE TYPE status_enum AS ENUM ('active', 'inactive')` before the table, and the column uses that type. This gives you database-level validation without CHECK constraints.

Frequently asked questions

How are enums handled in the generated PostgreSQL DDL?

With native CREATE TYPE … AS ENUM statements. The enum type is created before the table that uses it, and the column references the type — not a CHECK constraint or a plain VARCHAR.

Does the converter use SERIAL or IDENTITY columns?

SERIAL. A single integer primary key becomes SERIAL PRIMARY KEY (BIGSERIAL for bigint). Columns that are both PK and FK — the one-to-one child pattern — stay plain INTEGER so the value can mirror the parent key.

Are timestamps timezone-aware?

Yes — the abstract timestamp type maps to TIMESTAMPTZ. If you need a naive timestamp, declare the column type explicitly in the diagram.

Can I add CHECK constraints and partial indexes from the diagram?

Yes. `::CHECK(price > 0)` emits an inline CHECK, and `::INDEX([email], where: "deleted_at IS NULL")` emits a partial index with a WHERE clause — both PostgreSQL-native features the converter supports directly.

Related conversions