Mermaid ER-Diagramm Editor
Ein Entity-Relationship-Diagramm zeigt Tabellen, ihre Spalten und wie sie verknüpft sind. Nimm es, wenn es um ein Datenbankschema geht und die interessanten Fragen Schlüssel und Kardinalität betreffen — eins zu vielen, optional oder über eine Verknüpfungstabelle. Für Typen mit Verhalten und Vererbung nimm ein Klassendiagramm.
Ein normalisiertes Bestellschema mit Verknüpfungstabelle
Die Verknüpfungstabelle BESTELLPOSITION ist der lehrreiche Teil: So drückt man eine n:m-Beziehung ehrlich aus — über eine eigene Tabelle mit eigenen Spalten — statt so zu tun, als wären zwei Tabellen direkt verbunden.
erDiagram
KUNDE ||--o{ BESTELLUNG : erteilt
BESTELLUNG ||--|{ BESTELLPOSITION : enthält
ARTIKEL ||--o{ BESTELLPOSITION : "erscheint in"
KUNDE ||--o{ ADRESSE : "liefert an"
KUNDE {
int id PK
string email UK "beim Speichern kleingeschrieben"
string name
datetime erstellt_am
}
BESTELLUNG {
int id PK
int kunde_id FK
string status
decimal gesamtbetrag
}
BESTELLPOSITION {
int bestellung_id PK, FK
int artikel_id PK, FK
int menge
decimal einzelpreis "Preis zum Bestellzeitpunkt"
}
ARTIKEL {
int id PK
string artikelnummer UK
string bezeichnung
}
ADRESSE {
int id PK
int kunde_id FK
string plz
}Durchgearbeitete Beispiele
1. Zwei Entitäten und eine Beziehung
Jede ER-Beziehung braucht nach dem Doppelpunkt eine Beschriftung — anders als bei einer Flussdiagramm-Kante ist sie Pflicht. Lies es als Satz: KUNDE erteilt BESTELLUNG.
erDiagram
KUNDE ||--o{ BESTELLUNG : erteilt2. Spalten ergänzen
Jede Attributzeile ist `Typ Name`, und beide Teile sind Pflicht. `PK`, `FK` und `UK` markieren Schlüssel; eine Zeichenkette in Anführungszeichen am Ende ist ein Kommentar.
erDiagram
KUNDE ||--o{ BESTELLUNG : erteilt
KUNDE {
int id PK
string email UK
string name
}
BESTELLUNG {
int id PK
int kunde_id FK
datetime erfasst_am "UTC"
}3. Kardinalität, die etwas aussagt
Die beiden Zeichen direkt an einer Entität sind ihre Kardinalität. Dieses Beispiel sagt: Eine Bestellung muss mindestens eine Position haben, ein Kunde darf aber gar keine Bestellung haben — eine echte Einschränkung, die das Schema erzwingen und das Diagramm zeigen sollte.
erDiagram
KUNDE ||--o{ BESTELLUNG : erteilt
BESTELLUNG ||--|{ BESTELLPOSITION : enthält
BESTELLPOSITION }o--|| ARTIKEL : verweist_auf4. n:m über eine Verknüpfungstabelle
Mermaid kann eine direkte n:m-Beziehung zeichnen, aber ein Schema hat selten eine — darunter liegt eine Verknüpfungstabelle. Sie zu zeichnen ist ehrlicher und gibt dir einen Ort für die Spalten, die zur Beziehung selbst gehören.
erDiagram
STUDENT ||--o{ BELEGUNG : "schreibt sich ein für"
KURS ||--o{ BELEGUNG : "wird belegt über"
BELEGUNG {
int student_id PK, FK
int kurs_id PK, FK
datetime eingeschrieben_am
string note "leer bis zur Bewertung"
}
STUDENT {
int id PK
string name
}
KURS {
int id PK
string kuerzel UK
}5. Beziehungen auf sich selbst
Eine Tabelle kann sich auf sich selbst beziehen — eine Berichtslinie, ein Kategoriebaum, ein Kommentarstrang. Die Beschriftung ist hier wichtiger als sonst, weil beide Enden dieselbe Entität sind.
erDiagram
MITARBEITER ||--o{ MITARBEITER : führt
MITARBEITER {
int id PK
int vorgesetzter_id FK "leer bei der Geschäftsführung"
string name
string funktion
}Syntaxreferenz für ER-Diagramme
Die Kardinalität steht als zwei Zeichen an jedem Ende der Beziehung und liest sich von der Mitte nach außen. Das linke Paar beschreibt die linke Entität, das rechte Paar die rechte.
| Syntax | Bedeutung |
|---|---|
| erDiagram | Öffnet das Diagramm. Groß-/Kleinschreibung zählt. |
| A ||--o{ B : Text | Beziehung. Die Beschriftung ist Pflicht. |
| || | Genau eins. |
| o| | Null oder eins. |
| }| | Eins oder mehr. |
| }o | Null oder mehr. |
| -- | Identifizierende Beziehung — durchgezogene Linie. |
| .. | Nicht identifizierende Beziehung — gestrichelte Linie. |
| A { ... } | Attributblock für Entität A. |
| int id PK | Attribut: Typ, dann Name, dann optionale Schlüsselmarkierung. |
| PK / FK / UK | Primär-, Fremd-, eindeutiger Schlüssel. |
| int id PK, FK | Mehrere Schlüsselmarkierungen, durch Komma getrennt. |
| string email "Kommentar" | Zeichenkette am Ende ist ein Kommentar zur Spalte. |
| A ||--o{ B : "zwei Wörter" | Anführungszeichen sind bei jeder Beschriftung mit Leerzeichen PFLICHT. Ohne sie bricht die Beschriftung am ersten Leerzeichen ab, und jedes weitere Wort wird zu einer Geister-Entität. |
Fehler, die ER-Diagramme zerlegen
ER-Diagramme haben die strengste Grammatik der sechs Typen hier — was anderswo problemlos rendert, wird hier rundheraus zurückgewiesen. Alles nachgestellt mit Mermaid 11.12.2.
Was du siehst
Parse error, endet mit: Expecting 'COLON', 'STYLE_SEPARATOR', got 'NEWLINE'
Warum
Eine Beziehung ohne Beschriftung. Anders als bei einer Flussdiagramm-Kante sind Doppelpunkt und Beschriftung Pflicht — ohne sie endet die Zeile schlicht zu früh.
Lösung
Doppelpunkt und ein Verb ergänzen. Kurz genug, dass es sich als Satz liest.
erDiagram
KUNDE ||--o{ BESTELLUNGerDiagram
KUNDE ||--o{ BESTELLUNG : erteiltWas du siehst
Parse error, endet mit: got 'UNICODE_TEXT'
Warum
Ein ungültiges Kardinalitätszeichen. Gültig sind nur `||`, `o|`, `}|` und `}o` (sowie ihre Spiegelungen); alles andere scheitert. `oo` ist der übliche Tippfehler, weil man die Notation für symmetrisch hält.
Lösung
Eines der vier Paare verwenden. `||--o{` — genau eins zu null oder mehr — deckt die meisten Fremdschlüssel ab.
erDiagram
KUNDE ||--oo{ BESTELLUNG : erteilterDiagram
KUNDE ||--o{ BESTELLUNG : erteiltWas du siehst
Parse error, endet mit: Expecting 'ATTRIBUTE_WORD', got 'BLOCK_STOP'
Warum
Ein Attribut mit Namen, aber ohne Typ. ER-Attribute sind `Typ Name`, und der Typ ist nicht optional — was alle überrascht, die von schemalosen Datenbanken kommen.
Lösung
Jedem Attribut einen Typ geben. Erfinde einen, wenn das echte Schema keinen hat: `string`, `int`, `json`.
erDiagram
KUNDE {
email
}erDiagram
KUNDE {
string email
}Was du siehst
No diagram type detected matching given configuration
Warum
Falsche Groß-/Kleinschreibung. `erdiagram` und `ERDiagram` scheitern beide; nur `erDiagram` funktioniert.
Lösung
Kleines e, großes D.
erdiagram
A ||--o{ B : haterDiagram
A ||--o{ B : hatWas du siehst
Parse error, endet mit: Expecting 'NON_IDENTIFYING', 'IDENTIFYING', got 'UNICODE_TEXT'
Warum
Die Linie zwischen den beiden Kardinalitätszeichen ist falsch. Es müssen genau zwei Zeichen sein — `--` für eine identifizierende oder `..` für eine nicht identifizierende Beziehung. Ein einzelner Bindestrich ist keine Kurzform von `--`, sondern ein Syntaxfehler.
Lösung
`--` oder `..` zwischen die Kardinalitätspaare setzen.
erDiagram
KUNDE ||-o{ BESTELLUNG : erteilterDiagram
KUNDE ||--o{ BESTELLUNG : erteiltWas du siehst
Die Kardinalität rendert, beschreibt aber die umgekehrte Einschränkung
Warum
Die beiden Zeichen direkt an einer Entität gehören zu dieser Entität, und man liest sie leicht falsch herum. `KUNDE ||--o{ BESTELLUNG` sagt, ein Kunde hat null oder mehr Bestellungen. Dreh es zu `KUNDE }o--|| BESTELLUNG` um, und du hast gesagt, jeder Kunde gehöre zu genau einer Bestellung — Unsinn, der ohne Murren gerendert wird.
Lösung
Von der Mitte nach außen lesen: Die Zeichen an KUNDE beschreiben, wie viele Kunden es gibt, nicht wie viele Bestellungen.
erDiagram
KUNDE }o--|| BESTELLUNG : erteilterDiagram
KUNDE ||--o{ BESTELLUNG : erteiltHinweise zum Rendern
Gemessen an Mermaid 11.12.2, so wie diese Seite es einsetzt.
Das Layout treiben die Beziehungen, nicht die Zahl der Entitäten
Eine Kette von Entitäten, die jeweils mit der nächsten verbunden sind, wird zu einer hohen Säule — vierzig Entitäten ergeben eine viewBox um 116×7500. Dieselben vierzig Entitäten alle an einer zentralen Tabelle ergeben etwas viel Breiteres und Flacheres. Das ist der einzige Diagrammtyp hier, bei dem die Form deiner Daten das Bild stärker verändert als ihre Menge. Ein Schema, das nicht passen will, rettet man deshalb oft dadurch, dass man andere Beziehungen zeichnet — nicht weniger.
Die Grammatik ist die strengste der sechs Typen
Beziehungsbeschriftungen sind Pflicht, Attributtypen sind Pflicht, und die Kardinalitätszeichen sind eine geschlossene Menge. Verglichen mit Gantt, wo fast alles rendert und Fehler still bleiben, scheitern ER-Diagramme laut und früh. Das ist ein Vorteil: Wenn ein ER-Diagramm rendert, ist es sehr viel wahrscheinlicher das Diagramm, das du gemeint hast.
Beschriftungen sind HTML, deshalb rendert der PNG-Export neu
Die Attributtabellen der Entitäten stecken in einem SVG-`<foreignObject>`, das Browser nicht direkt auf ein Canvas zeichnen können. Der PNG-Export dieser Seite gab früher still eine SVG-Datei zurück; inzwischen rendert er zuerst mit reinen SVG-Textbeschriftungen neu und liefert ein korrektes PNG in voller Größe mit geringfügig anderer Typografie.
Entitätsnamen unterscheiden Groß- und Kleinschreibung, üblich ist Großschreibung
`KUNDE` und `kunde` sind zwei verschiedene Entitäten, und wer beides im selben Diagramm verwendet, bekommt stillschweigend zwei Kästen. Die Großschreibung erzwingt Mermaid nicht, aber sie lohnt sich genau deshalb: Ein versehentlich kleingeschriebener Verweis fällt sofort auf.
Das Theme ändert Farben, niemals das Layout
Helles und dunkles Theme ergeben für dieselbe Quelle eine identische viewBox; Attributtabellen können beim Themewechsel also nicht umbrechen oder abgeschnitten werden.
Wann etwas anderes besser passt
Brauchst du Vererbung, Schnittstellen oder Methoden, ist das der falsche Diagrammtyp — ER kennt nichts davon. Nimm ein Klassendiagramm und nimm in Kauf, dass es deinen Code abbildet und nicht deine Tabellen.
Ist das Schema groß, wird ein ER-Diagramm davon zur Tapete, die niemand liest. Zeichne die fünf Tabellen, um die es gerade geht, und lass den Rest weg; ein Diagramm ist ein Argument, kein Inventar.
Und geht es eigentlich darum, wie Daten zwischen Systemen fließen statt wie sie abgelegt sind, beantwortet das ein Flussdiagramm mit Subgraphen pro System — ein ER-Diagramm nicht.
Andere Diagrammtypen
Geschrieben von Dominik Malsch · Zuletzt aktualisiert: