Mermaid ER Syntax

Last updated: March 2026

Mermaid ER diagrams are a plain-text format for describing entity-relationship schemas. Diagram2Code parses Mermaid erDiagram blocks and converts them to production-ready SQL DDL or ORM model code. This page covers the input syntax accepted by the parser — for output details see SQL DDL Generation and ORM Generation.

Diagram2Code supports Mermaid erDiagram blocks only. Other Mermaid diagram types (flowchart, sequence, Gantt, etc.) are not parsed and will produce a PARSE_ERROR.

Table & Column Syntax

Each entity block defines one database table. The block opens with the table name in UPPER_SNAKE_CASE (converted to lower_snake_case in SQL output), followed by a brace-enclosed list of column definitions.

erDiagram
    TABLE_NAME {
        type column_name MARKERS "optional comment"
    }

Each column line contains up to four parts in order:

PartRequiredDescription
typeYesAbstract type (int, string, decimal, boolean, timestamp, uuid, text, json, blob) or a native database type (bigint, varchar(255), varchar2(255), etc.)
column_nameYesIdentifier in snake_case. Column names may not contain spaces.
markersNoOne or more of PK (primary key), FK (foreign key), UK (unique constraint). Multiple markers are separated by spaces: PK UK.
"comment"NoA double-quoted string that appears as a column comment in the generated SQL (where supported by the dialect).

Relationships

Relationships are declared outside entity blocks, one per line. They define the foreign key targets that the generator uses to emit REFERENCES clauses and ORM association annotations.

LEFT_TABLE CARDINALITY "--" CARDINALITY RIGHT_TABLE : "label"

The cardinality tokens use Mermaid's crow's-foot notation. Each side of the -- separator is two characters: the first describes optionality, the second describes multiplicity.

TokenMeaning
||Exactly one (mandatory, singular)
|o / o|Zero or one (optional, singular)
}| / |{One or more (mandatory, many)
}o / o{Zero or more (optional, many)
Relationship examples
erDiagram
    CUSTOMER ||--o{ ORDER : places
    ORDER }|--|{ PRODUCT : contains
    USER ||--|| PROFILE : has

CUSTOMER ||--o{ ORDER : places means one Customer places zero-or-more Orders. The generator emits a foreign key from ORDER.customer_id back to CUSTOMER. The relationship label (places) is used for documentation only and does not affect the SQL output.

A many-to-many relationship (}|--|{) causes Diagram2Code to generate a junction table automatically. The junction table is named by joining the two table names in alphabetical order (e.g. order_product) and contains foreign key columns to each parent table.

Common Patterns

One-to-many with explicit FK column

Blog posts belonging to an author
erDiagram
    AUTHOR {
        int id PK
        string name
        string email UK
    }
    POST {
        int id PK
        int author_id FK
        string title
        text body
        timestamp published_at
    }
    AUTHOR ||--o{ POST : writes

Many-to-many via junction table

Declare the relationship directly — Diagram2Code generates the junction table automatically. You do not need to define it as a separate entity.

Students enrolled in courses
erDiagram
    STUDENT {
        int id PK
        string name
        string email UK
    }
    COURSE {
        int id PK
        string title
        string code UK
    }
    STUDENT }|--|{ COURSE : enrolls

Self-referencing table

A table can reference itself, which is common for hierarchical data such as categories or org charts.

Category tree with parent reference
erDiagram
    CATEGORY {
        int id PK
        string name
        int parent_id FK "NULL for root categories"
    }
    CATEGORY ||--o{ CATEGORY : contains

Full-featured Example

E-commerce schema — all column features
erDiagram
    CATEGORY {
        int id PK
        string name UK "Category name"
        int parent_id FK
    }
    PRODUCT {
        int id PK "Primary key"
        string name "Product name"
        decimal price
        boolean active
        string sku UK "Stock keeping unit"
        int category_id FK
        timestamp created_at
    }
    CUSTOMER {
        int id PK
        string email UK
        string name
        timestamp created_at
    }
    ORDER {
        int id PK
        int customer_id FK
        decimal total
        timestamp placed_at
    }
    CATEGORY ||--o{ CATEGORY : contains
    CATEGORY ||--o{ PRODUCT : groups
    CUSTOMER ||--o{ ORDER : places
    ORDER }|--|{ PRODUCT : includes

Known Limitations