Бесплатно · Без регистрации · Поддержка файлов .mmd

Редактор ER-диаграмм Mermaid

ER-диаграмма показывает таблицы, их столбцы и то, как они соединяются. Она уместна, когда предмет — схема базы данных, а интересные вопросы касаются ключей и кратности: один-ко-многим, необязательная связь, связь через промежуточную таблицу. Для типов с поведением и наследованием берите диаграмму классов.

Нормализованная схема заказов со связующей таблицей

Внимания заслуживает `}o--||` у строки заказа: так честно выражается связь многие-ко-многим — через промежуточную таблицу с собственными столбцами, а не притворством, будто две таблицы соединяются напрямую. Хранение цены в строке заказа, а не только в товаре, — то самое решение, которое диаграмма и должна показывать.

erDiagram
    КЛИЕНТ ||--o{ ЗАКАЗ : оформляет
    ЗАКАЗ ||--|{ СТРОКА_ЗАКАЗА : содержит
    ТОВАР ||--o{ СТРОКА_ЗАКАЗА : "встречается в"
    КЛИЕНТ ||--o{ АДРЕС : "доставка по"

    КЛИЕНТ {
        int id PK
        string почта UK "хранится в нижнем регистре"
        string фио
        datetime создан
    }
    ЗАКАЗ {
        int id PK
        int клиент_id FK
        string статус
        decimal сумма
    }
    СТРОКА_ЗАКАЗА {
        int заказ_id PK, FK
        int товар_id PK, FK
        int количество
        decimal цена "цена на момент заказа"
    }
    ТОВАР {
        int id PK
        string артикул UK
        string название
    }
    АДРЕС {
        int id PK
        int клиент_id FK
        string индекс
    }
Открыть в редакторе
Реклама

Разобранные примеры

1. Две сущности и одна связь

Каждой связи в ER нужна подпись после двоеточия — в отличие от ребра блок-схемы, она не необязательна. Читается как предложение: КЛИЕНТ оформляет ЗАКАЗ.

erDiagram
    КЛИЕНТ ||--o{ ЗАКАЗ : оформляет
Открыть в редакторе

2. Добавляем столбцы

Каждая строка атрибута — это `тип имя`, и обе части обязательны. `PK`, `FK` и `UK` отмечают ключи; строка в кавычках в конце — это комментарий.

erDiagram
    КЛИЕНТ ||--o{ ЗАКАЗ : оформляет
    КЛИЕНТ {
        int id PK
        string почта UK
        string фио
    }
    ЗАКАЗ {
        int id PK
        int клиент_id FK
        datetime оформлен "в UTC"
    }
Открыть в редакторе

3. Кратность, которая что-то сообщает

Два символа, ближайшие к каждой сущности, — это её кратность. Этот пример говорит, что в заказе обязана быть хотя бы одна строка, но у клиента может не быть ни одного заказа: реальное ограничение, которое схема должна соблюдать, а диаграмма — показывать.

erDiagram
    КЛИЕНТ ||--o{ ЗАКАЗ : оформляет
    ЗАКАЗ ||--|{ СТРОКА_ЗАКАЗА : содержит
    СТРОКА_ЗАКАЗА }o--|| ТОВАР : ссылается
Открыть в редакторе

4. Многие-ко-многим через связующую таблицу

Mermaid умеет рисовать прямую связь многие-ко-многим, но в схеме её почти никогда нет: под ней лежит промежуточная таблица. Нарисовать её честнее, и появляется место для столбцов, принадлежащих самой связи.

erDiagram
    СТУДЕНТ ||--o{ ЗАПИСЬ : "записывается на"
    КУРС ||--o{ ЗАПИСЬ : "изучается через"
    ЗАПИСЬ {
        int студент_id PK, FK
        int курс_id PK, FK
        datetime записан
        string оценка "пусто до аттестации"
    }
    СТУДЕНТ {
        int id PK
        string фио
    }
    КУРС {
        int id PK
        string код UK
    }
Открыть в редакторе

5. Связь с самой собой

Таблица может быть связана сама с собой: линия подчинения, дерево категорий, ветка комментариев. Подпись связи здесь важнее обычного, потому что оба конца — одна и та же сущность.

erDiagram
    СОТРУДНИК ||--o{ СОТРУДНИК : руководит
    СОТРУДНИК {
        int id PK
        int руководитель_id FK "пусто у директора"
        string фио
        string должность
    }
Открыть в редакторе

Справочник синтаксиса ER-диаграммы

Кратность записывается двумя символами на каждом конце связи и читается от середины наружу. Левая пара описывает левую сущность, правая — правую.

СинтаксисЗначение
erDiagramОткрывает диаграмму. Регистр важен: `erdiagram` не работает.
A ||--o{ B : подписьСвязь. Подпись обязательна.
||Ровно один.
o|Ноль или один.
}|Один или больше.
}oНоль или больше.
--Идентифицирующая связь — сплошная линия.
..Неидентифицирующая связь — пунктир.
A { ... }Блок атрибутов сущности A.
int id PKАтрибут: тип, затем имя, затем необязательная пометка ключа.
PK / FK / UKПервичный, внешний, уникальный ключ.
int id PK, FKНесколько пометок ключа через запятую.
string почта "комментарий"Строка в кавычках в конце — комментарий к столбцу.
A ||--o{ B : "принадлежит к"Кавычки ОБЯЗАТЕЛЬНЫ, как только в подписи есть пробел. Без них подпись обрывается на первом пробеле, а каждое оставшееся слово становится лишней сущностью.
Реклама

Шесть ошибок, ломающих ER-диаграмму

У ER самая строгая грамматика из шести типов: то, что проходит в других диаграммах, здесь отвергается сразу. Но есть и тихая ошибка, и по-русски она встречается чаще, чем кажется. Всё воспроизведено на Mermaid 11.12.2.

Что вы видите

Диаграмма рисуется, подпись обрезана, а на схеме появились неизвестные сущности

Почему

Подпись связи с пробелом и без кавычек. По-русски однословные глаголы вроде «оформляет» или «содержит» спасают часто, но не всегда: «принадлежит к», «встречается в», «доставка по» — обычные для схемы формулировки. Измерено: `КЛИЕНТ ||--o{ ЗАКАЗ : принадлежит к` не даёт ошибки, обрезает подпись до «принадлежит» и создаёт пустую сущность с именем «к». Две таблицы рисуются тремя прямоугольниками, и ничего об этом не сообщает.

Решение

Берите в кавычки любую подпись с пробелом. Проще сделать это правилом, чем каждый раз решать заново.

Ошибка
erDiagram
    КЛИЕНТ ||--o{ ЗАКАЗ : принадлежит к
Исправлено
erDiagram
    КЛИЕНТ ||--o{ ЗАКАЗ : "принадлежит к"

Что вы видите

Parse error, заканчивается на: Expecting 'COLON', 'STYLE_SEPARATOR', got 'NEWLINE'

Почему

Связь без подписи. В отличие от ребра блок-схемы, двоеточие и подпись обязательны — без них строка просто заканчивается слишком рано.

Решение

Добавьте двоеточие и глагол, в кавычках, если в подписи есть пробел.

Ошибка
erDiagram
    КЛИЕНТ ||--o{ ЗАКАЗ
Исправлено
erDiagram
    КЛИЕНТ ||--o{ ЗАКАЗ : оформляет

Что вы видите

Parse error, заканчивается на: got 'UNICODE_TEXT'

Почему

Недопустимый токен кратности. Допустимы только `||`, `o|`, `}|` и `}o` (и их зеркальные варианты); всё остальное падает. `oo` — обычная опечатка, от ожидания, что нотация симметрична.

Решение

Используйте одну из четырёх пар. `||--o{` — ровно один к нулю или больше — покрывает большинство внешних ключей.

Ошибка
erDiagram
    КЛИЕНТ ||--oo{ ЗАКАЗ : оформляет
Исправлено
erDiagram
    КЛИЕНТ ||--o{ ЗАКАЗ : оформляет

Что вы видите

Parse error, заканчивается на: Expecting 'ATTRIBUTE_WORD', got 'BLOCK_STOP'

Почему

У атрибута есть имя, но нет типа. Атрибуты ER записываются как `тип имя`, и тип не является необязательным — это удивляет тех, кто пришёл из баз без схемы.

Решение

Дайте тип каждому атрибуту. Придумайте его, если в реальной схеме типа нет: `string`, `int`, `json`.

Ошибка
erDiagram
    КЛИЕНТ {
        почта
    }
Исправлено
erDiagram
    КЛИЕНТ {
        string почта
    }

Что вы видите

Parse error, заканчивается на: Expecting 'NON_IDENTIFYING', 'IDENTIFYING', got 'UNICODE_TEXT'

Почему

Неверная линия между двумя пометками кратности. Она должна быть ровно из двух символов: `--` для идентифицирующей связи или `..` для неидентифицирующей. Один дефис — это не сокращённая запись `--`, а синтаксическая ошибка.

Решение

Между парами кратности пишите `--` или `..`.

Ошибка
erDiagram
    КЛИЕНТ ||-o{ ЗАКАЗ : оформляет
Исправлено
erDiagram
    КЛИЕНТ ||--o{ ЗАКАЗ : оформляет

Что вы видите

Кратность рисуется, но описывает противоположное ограничение

Почему

Два символа, ближайшие к сущности, принадлежат именно ей, и прочитать их наоборот очень легко. `КЛИЕНТ ||--o{ ЗАКАЗ` говорит, что у одного клиента ноль или больше заказов. Переверните в `КЛИЕНТ }o--|| ЗАКАЗ` — и вы заявили, что каждый клиент принадлежит ровно одному заказу, что бессмысленно, и при этом рисуется без возражений.

Решение

Читайте от середины наружу: значки, касающиеся КЛИЕНТА, описывают, сколько клиентов, а не сколько заказов.

Ошибка
erDiagram
    КЛИЕНТ }o--|| ЗАКАЗ : оформляет
Исправлено
erDiagram
    КЛИЕНТ ||--o{ ЗАКАЗ : оформляет

Заметки о рендеринге

Измерено на том Mermaid 11.12.2, который использует сайт.

Раскладку определяют связи, а не количество сущностей

Цепочка сущностей, где каждая связана со следующей, рисуется высоким столбцом: сорок сущностей дают viewBox около 116×7315 против 116×470 при трёх. Но те же сорок сущностей, связанных с одной центральной таблицей, дают нечто гораздо более широкое и низкое. Это единственный тип диаграмм здесь, где форма ваших данных меняет форму картинки сильнее, чем её объём: схему, которая не помещается, чаще удаётся починить сменой того, какие связи вы рисуете, а не их количества.

Кириллица работает, но заглавные буквы теряют роль подсказки

Проверено: `КЛИЕНТ`, `почта` и `фио` работают как имена сущностей, столбцов и типов. Но традиция писать сущности заглавными в английском полезна ещё и тем, что делает заметной случайную ссылку строчными: `CUSTOMER` и `customer` — две разные сущности и два прямоугольника без предупреждения. То же самое верно и для кириллицы, и вдобавок у нас есть свой источник расхождений — буква ё: `ЗАЁМ` и `ЗАЕМ` дадут две разные таблицы. Решите написание сущностей заранее и держитесь его.

Грамматика самая строгая из шести типов

Подписи связей обязательны, типы атрибутов обязательны, а токены кратности образуют закрытый набор. По сравнению с Гантом, где рисуется почти всё и ошибки молчат, ER падает рано и громко. Это достоинство: если ER-диаграмма нарисовалась, велика вероятность, что это именно та диаграмма, которую вы имели в виду, — за заметным исключением подписей без кавычек.

Подписи — это HTML, поэтому экспорт в PNG перерисовывает

Таблицы атрибутов сущностей рисуются внутри `<foreignObject>` в SVG, поэтому браузеры не могут растрировать их на canvas напрямую. Раньше экспорт в PNG на этом сайте молча отдавал SVG-файл; теперь он сначала перерисовывает диаграмму подписями обычным SVG-текстом и выдаёт правильный PNG в полном размере, с едва заметно иной типографикой.

Тема меняет цвета, но никогда — геометрию

Светлая и тёмная темы дают одинаковый viewBox для одного исходника, так что таблицы атрибутов не перекомпоновываются и не обрезаются при смене темы.

Когда лучше взять другую диаграмму

Если нужны наследование, интерфейсы или методы, это неподходящая диаграмма: в ER нет ни одного из этих понятий. Возьмите диаграмму классов и примите, что она моделирует ваш код, а не ваши таблицы.

Если схема большая, ER-диаграмма всей схемы превращается в настенный плакат, который никто не читает. Нарисуйте пять таблиц, относящихся к тому, что вы объясняете, а остальное оставьте за кадром: диаграмма — это довод, а не опись.

А если настоящий вопрос в том, как данные движутся между системами, а не как они хранятся, ответ даст блок-схема с подграфом на каждую систему, а ER-диаграмма — нет.

Другие типы диаграмм

Автор Dominik Malsch · Обновлено:

Открыть редактор →