Edytor diagramów ER Mermaid
Diagram związków encji pokazuje tabele, ich kolumny i sposób, w jaki się łączą. Nadaje się wtedy, gdy tematem jest schemat bazy danych, a ciekawe pytania dotyczą kluczy i liczności — jeden do wielu, opcjonalnie, albo przez tabelę łączącą. Do typów z zachowaniem i dziedziczeniem lepszy jest diagram klas.
Znormalizowany schemat zamówień z tabelą łączącą
Wartą uwagi częścią jest `}o--||` przy pozycji zamówienia: tak wyraża się uczciwie relację wiele do wielu, przez tabelę łączącą z własnymi kolumnami, zamiast udawać, że dwie tabele łączą się bezpośrednio. Przechowywanie ceny w pozycji, a nie tylko w produkcie, to właśnie decyzja, którą diagram powinien uwidocznić.
erDiagram
KLIENT ||--o{ ZAMOWIENIE : "składa"
ZAMOWIENIE ||--|{ POZYCJA : "zawiera"
PRODUKT ||--o{ POZYCJA : "występuje w"
KLIENT ||--o{ ADRES : "wysyłka na"
KLIENT {
int id PK
string email UK "zapisywany małymi literami"
string nazwa
datetime utworzony
}
ZAMOWIENIE {
int id PK
int klient_id FK
string status
decimal wartosc
}
POZYCJA {
int zamowienie_id PK, FK
int produkt_id PK, FK
int ilosc
decimal cena "cena z chwili złożenia zamówienia"
}
PRODUKT {
int id PK
string sku UK
string nazwa
}
ADRES {
int id PK
int klient_id FK
string kod_pocztowy
}Omówione przykłady
1. Dwie encje i jedna relacja
Każda relacja ER wymaga etykiety po dwukropku — nie jest opcjonalna, inaczej niż krawędź schematu blokowego. Czyta się to jak zdanie: KLIENT składa ZAMOWIENIE.
erDiagram
KLIENT ||--o{ ZAMOWIENIE : "składa"2. Dodawanie kolumn
Każdy wiersz atrybutu to `typ nazwa` i obie części są obowiązkowe. `PK`, `FK` i `UK` oznaczają klucze; napis w cudzysłowie na końcu jest komentarzem do kolumny.
erDiagram
KLIENT ||--o{ ZAMOWIENIE : "składa"
KLIENT {
int id PK
string email UK
string nazwa
}
ZAMOWIENIE {
int id PK
int klient_id FK
datetime zlozone "w UTC"
}3. Liczność, która coś mówi
Dwa znaki najbliżej każdej encji to jej liczność. Ten przykład mówi, że zamówienie musi mieć co najmniej jedną pozycję, ale klient może nie mieć żadnego zamówienia: realne ograniczenie, które schemat powinien wymuszać, a diagram pokazywać.
erDiagram
KLIENT ||--o{ ZAMOWIENIE : "składa"
ZAMOWIENIE ||--|{ POZYCJA : "zawiera"
POZYCJA }o--|| PRODUKT : "odwołuje się do"4. Wiele do wielu przez tabelę łączącą
Mermaid potrafi narysować bezpośrednią relację wiele do wielu, ale schemat prawie nigdy jej nie ma: pod spodem leży tabela łącząca. Narysowanie jej jest uczciwsze i daje miejsce na kolumny należące do samej relacji.
erDiagram
STUDENT ||--o{ ZAPIS : "zapisuje się na"
KURS ||--o{ ZAPIS : "realizowany przez"
ZAPIS {
int student_id PK, FK
int kurs_id PK, FK
datetime data_zapisu
string ocena "pusta do czasu zaliczenia"
}
STUDENT {
int id PK
string nazwisko
}
KURS {
int id PK
string kod UK
}5. Relacje zwrotne
Tabela może wiązać się sama ze sobą: linia podległości, drzewo kategorii, wątek komentarzy. Etykieta relacji ma tu większe znaczenie niż zwykle, bo oba końce to ta sama encja.
erDiagram
PRACOWNIK ||--o{ PRACOWNIK : "kieruje"
PRACOWNIK {
int id PK
int przelozony_id FK "puste dla zarządu"
string nazwisko
string stanowisko
}Ściąga ze składni diagramu ER
Liczność zapisuje się dwoma znakami na każdym końcu relacji i czyta od środka na zewnątrz. Lewa para opisuje encję po lewej, prawa tę po prawej.
| Składnia | Znaczenie |
|---|---|
| erDiagram | Otwiera diagram. Rozróżnia wielkość liter: `erdiagram` nie zadziała. |
| A ||--o{ B : "etykieta" | Relacja. Etykieta jest obowiązkowa. |
| || | Dokładnie jeden. |
| o| | Zero albo jeden. |
| }| | Jeden albo więcej. |
| }o | Zero albo więcej. |
| -- | Relacja identyfikująca — linia ciągła. |
| .. | Relacja nieidentyfikująca — linia przerywana. |
| A { ... } | Blok atrybutów encji A. |
| int id PK | Atrybut: typ, potem nazwa, potem opcjonalne oznaczenie klucza. |
| PK / FK / UK | Klucz główny, obcy, unikalny. |
| int id PK, FK | Kilka oznaczeń klucza, rozdzielonych przecinkiem. |
| string email "komentarz" | Napis w cudzysłowie na końcu to komentarz do kolumny. |
| A ||--o{ B : "należy do" | Cudzysłowy są OBOWIĄZKOWE, gdy tylko etykieta zawiera spację. Bez nich urywa się na pierwszej spacji, a każdy pozostały wyraz staje się encją widmem. |
Sześć błędów, które psują diagram ER
ER ma najostrzejszą gramatykę spośród sześciu typów: to, co przechodzi w innych diagramach, tutaj jest odrzucane wprost. Ma jednak także cichy błąd, na który po polsku wpada się szczególnie łatwo. Wszystko odtworzone na Mermaidzie 11.12.2.
Co widzisz
Rysuje się, etykieta jest ucięta, a na diagramie pojawiają się encje, których nie napisałeś
Dlaczego
Etykieta relacji zawiera spację i nie ma cudzysłowów. To błąd, który po polsku będzie przeszkadzał najbardziej, bo nasze zwroty relacyjne prawie zawsze są wielowyrazowe: «należy do», «występuje w», «wysyłka na». Zmierzone: `KLIENT ||--o{ ZAMOWIENIE : należy do` nie zgłasza błędu, skraca etykietę do «należy» i tworzy pustą encję o nazwie «do». Przy trzech wyrazach powstają dwie encje widma. Dwie tabele rysują się jako cztery prostokąty i nic o tym nie ostrzega.
Rozwiązanie
Bierz w cudzysłów każdą etykietę zawierającą spację. Po polsku znaczy to praktycznie zawsze; łatwiej przyjąć to jako zasadę niż rozstrzygać za każdym razem.
erDiagram
KLIENT ||--o{ ZAMOWIENIE : należy doerDiagram
KLIENT ||--o{ ZAMOWIENIE : "należy do"Co widzisz
Parse error, kończy się na: Expecting 'COLON', 'STYLE_SEPARATOR', got 'NEWLINE'
Dlaczego
Relacja bez etykiety. Inaczej niż w krawędzi schematu blokowego, dwukropek i etykieta są obowiązkowe: bez nich wiersz po prostu kończy się za wcześnie.
Rozwiązanie
Dodaj dwukropek i zwrot czasownikowy, w cudzysłowie, jeśli zawiera spację.
erDiagram
KLIENT ||--o{ ZAMOWIENIEerDiagram
KLIENT ||--o{ ZAMOWIENIE : "składa"Co widzisz
Parse error, kończy się na: got 'UNICODE_TEXT'
Dlaczego
Nieprawidłowy token liczności. Poprawne są wyłącznie `||`, `o|`, `}|` i `}o` (oraz ich lustrzane odbicia); cokolwiek innego się przewraca. `oo` to typowa literówka, brana z założenia, że notacja jest symetryczna.
Rozwiązanie
Użyj jednej z czterech par. `||--o{` — dokładnie jeden do zera lub więcej — pokrywa większość kluczy obcych.
erDiagram
KLIENT ||--oo{ ZAMOWIENIE : "składa"erDiagram
KLIENT ||--o{ ZAMOWIENIE : "składa"Co widzisz
Parse error, kończy się na: Expecting 'ATTRIBUTE_WORD', got 'BLOCK_STOP'
Dlaczego
Atrybut ma nazwę, ale nie ma typu. Atrybuty ER zapisuje się jako `typ nazwa`, a typ nie jest opcjonalny — co zaskakuje osoby przychodzące z baz bez schematu.
Rozwiązanie
Nadaj typ każdemu atrybutowi. Wymyśl go, jeśli prawdziwy schemat go nie ma: `string`, `int`, `json`.
erDiagram
KLIENT {
email
}erDiagram
KLIENT {
string email
}Co widzisz
Parse error, kończy się na: Expecting 'NON_IDENTIFYING', 'IDENTIFYING', got 'UNICODE_TEXT'
Dlaczego
Linia między dwoma oznaczeniami liczności jest niewłaściwa. Musi mieć dokładnie dwa znaki: `--` dla relacji identyfikującej albo `..` dla nieidentyfikującej. Pojedynczy myślnik nie jest skróconą wersją `--`, tylko błędem składni.
Rozwiązanie
Między parami liczności pisz `--` albo `..`.
erDiagram
KLIENT ||-o{ ZAMOWIENIE : "składa"erDiagram
KLIENT ||--o{ ZAMOWIENIE : "składa"Co widzisz
Liczność się rysuje, ale opisuje odwrotne ograniczenie
Dlaczego
Dwa znaki najbliżej każdej encji należą do tej właśnie encji, a przeczytanie ich na odwrót jest bardzo łatwe. `KLIENT ||--o{ ZAMOWIENIE` mówi, że jeden klient ma zero lub więcej zamówień. Odwróć to na `KLIENT }o--|| ZAMOWIENIE`, a stwierdzisz, że każdy klient należy do dokładnie jednego zamówienia, co nie ma sensu — i rysuje się bez najmniejszego sprzeciwu.
Rozwiązanie
Czytaj od środka na zewnątrz: znaki dotykające KLIENTA opisują, ilu jest klientów, a nie ile jest zamówień.
erDiagram
KLIENT }o--|| ZAMOWIENIE : "składa"erDiagram
KLIENT ||--o{ ZAMOWIENIE : "składa"Uwagi o renderowaniu
Zmierzone na Mermaidzie 11.12.2, którego używa ta strona.
Układ dyktują relacje, a nie liczba encji
Łańcuch encji powiązanych jedna z drugą rysuje się jako wysoka kolumna: czterdzieści encji daje viewBox około 116×7315, wobec 116×470 przy trzech. Ale te same czterdzieści encji powiązanych z jedną tabelą centralną daje coś znacznie szerszego i niższego. To jedyny typ diagramu tutaj, w którym kształt twoich danych zmienia kształt obrazka bardziej niż jego rozmiar, więc schemat, który się nie mieści, częściej naprawia się zmianą tego, które relacje rysujesz, niż ich liczby.
Po polsku prawie każda etykieta wymaga cudzysłowów
Warto to powtórzyć, bo to najdroższy cichy błąd na tej stronie. Angielskie etykiety relacji bywają jednowyrazowe — places, contains, references — więc w angielskiej dokumentacji cudzysłowy wyglądają na ozdobnik. Po polsku większość to zwroty wielowyrazowe i bez cudzysłowów się rozpadają. Zasada praktyczna: zawsze bierz etykietę w cudzysłów i przestań o tym myśleć.
Nazwy encji rozróżniają wielkość liter i umownie pisze się je wersalikami
`KLIENT` i `klient` to dwie różne encje, a wspomnienie obu w jednym diagramie daje dwa prostokąty bez ostrzeżenia. Konwencji wersalików Mermaid nie wymusza, ale warto ją trzymać właśnie dlatego, że uwidacznia przypadkowe odwołanie małymi literami. Polskie znaki działają w nazwach encji i kolumn bez problemu; warto natomiast z góry zdecydować, czy schemat ma ogonki, i się tego trzymać.
Gramatyka jest najostrzejsza spośród sześciu typów
Etykiety relacji są obowiązkowe, typy atrybutów również, a tokeny liczności tworzą zbiór zamknięty. W porównaniu z Ganttem, gdzie rysuje się niemal wszystko, a błędy milczą, ER przewraca się wcześnie i głośno. To zaleta: jeśli diagram ER się narysował, jest całkiem prawdopodobne, że to ten diagram, o który ci chodziło — z wyraźnym wyjątkiem etykiet bez cudzysłowów.
Etykiety to HTML, więc eksport do PNG przerysowuje
Tabele atrybutów encji rysowane są wewnątrz `<foreignObject>` w SVG, więc przeglądarki nie potrafią ich zrasteryzować wprost na canvasie. Eksport do PNG na tej stronie wcześniej po cichu oddawał plik SVG; teraz najpierw przerysowuje diagram etykietami z czystego tekstu SVG i wytwarza poprawny PNG w pełnym rozmiarze, z ledwie zauważalnie innym składem.
Kiedy lepszy będzie inny diagram
Jeśli potrzebujesz dziedziczenia, interfejsów albo metod, to niewłaściwy diagram: ER nie ma żadnego z tych pojęć. Użyj diagramu klas i przyjmij, że modeluje on twój kod, a nie twoje tabele.
Jeśli schemat jest duży, diagram ER całości staje się ścienną planszą, której nikt nie czyta. Narysuj pięć tabel związanych z tym, co właśnie tłumaczysz, a resztę zostaw poza kadrem; diagram jest argumentem, a nie inwentarzem.
A jeśli prawdziwe pytanie brzmi, jak dane przepływają między systemami, a nie jak są przechowywane, odpowie na nie schemat blokowy z podgrafem na system, a diagram ER nie.
Inne typy diagramów
Autor Dominik Malsch · Ostatnia aktualizacja: