תרשים ER
תרשים יחסי ישויות (בקיצור תרשים ER) מתאר דברים מעניינים בעלי זיקה הדדית בתחום ידע מסוים. תרשים ER בסיסי מורכב מסוגי ישויות (לסיווג הדברים המעניינים), ומציין את היחסים שיכולים להתקיים בין הישויות (המופעים של סוגי ישויות אלו).,שים לב שבפועל בדרך כלל מקצרים 'סוג ישות' ל-'ישות'. לדוגמה, 'סוג הישות CUSTOMER' ייקרא בדרך כלל פשוט 'הישות CUSTOMER'. נוהג זה נפוץ מאוד, ולכן לא מומלץ להשתמש בדרך אחרת; אך מבחינה טכנית, ישות היא מופע מופשט של סוג ישות, ותרשים ER מציג בדיוק מופעים מופשטים אלו ואת היחסים ביניהם. זו הסיבה שלשמות ישויות משתמשים תמיד בלשון יחיד.
העתק
הטמעה
---
title: Order example
---
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
CUSTOMER }|..|{ DELIVERY-ADDRESS : uses
שמות ישויות הם בדרך כלל באותיות גדולות, אם כי אין תקן מוסכם לכך, וגם התחביר של Mermaid אינו מחייב זאת.
היחסים בין הישויות מיוצגים בקווים עם סימוני קצה המציינים קרדינליות. Mermaid משתמשת בסימון כף העורב הנפוץ ביותר; כף העורב מציינת באופן חזותי שלישות שאליה היא מתחברת עשויים להיות מספר מופעים.
תרשים ER יכול לשמש למטרות שונות, ממודל לוגי מופשט שאינו מכיל פרטי מימוש, ועד למודל פיזי של טבלאות מסד נתונים יחסי. הכללת הגדרות תכונות בתרשים ER מסייעת להבין את ייעוד הישות ומשמעותה; הגדרות תכונות אלו אינן חייבות להיות ממצות, ולרוב חלק קטן מהתכונות מספיק. Mermaid מאפשרת להגדיר אותן לפי הסוג והשם שלהן.
העתק
הטמעה
erDiagram
CUSTOMER ||--o{ ORDER : places
CUSTOMER {
string name
string custNumber
string sector
}
ORDER ||--|{ LINE-ITEM : contains
ORDER {
int orderNumber
string deliveryAddress
}
LINE-ITEM {
string productCode
int quantity
float pricePerUnit
}
בעת הכללת תכונות בתרשים ER, עליך להחליט אם לכלול מפתח זר כתכונה; הדבר עשוי לתלות במידה שבה ברצונך לייצג את מבנה טבלת היחסים. אם התרשים שלך הוא מודל לוגי שאינו נועד לרמוז על מימוש יחסי, מוטב שלא לכלול תכונות אלו, מכיוון שהיחסים כבר מביעים כיצד הישויות קשורות זו לזו. לדוגמה, מבנה נתונים JSON יכול לממש יחס אחד-לרבים באמצעות מערך ללא תכונת מפתח זר. בדומה לכך, שפות תכנות מונחות עצמים יכולות להשתמש במצביעים או בהפניות לאוסף. גם עבור מודלים שנועדו למימוש יחסי, ייתכן שיהיה מקובל לחשוב שהכללת תכונת מפתח זר תציג כפילות של המידע שכבר מוצג ביחס, ולא תוסיף משמעות לישות.
תחביר
ישויות ויחסים
תחביר ה-Mermaid של תרשים ER תואם ל-PlantUML, ומורחב בפונקציונליות לסימון יחסים. כל הצהרה כוללת את הבאים:
העתק
הטמעה
<first-entity> [<relationship> <second-entity> : <relationship-label>]
- first-entity הוא שמו של הישות הראשונה. השם תומך בכל תו Unicode, ואם הוא עטוף במרכאות כפולות הוא יכול להכיל רווחים.
- relationship מתאר את היחס ההדדי בין שתי הישויות.
- second-entity הוא שמה של הישות האחרת.
- relationship-label מתאר את היחס מנקודת המבט של הישות הראשונה.
לדוגמה:
העתק
הטמעה
PROPERTY ||--|{ ROOM : contains
ניתן להבין הצהרה זו כך: נכס אחד מכיל חדר אחד או יותר, וחדר שייך לנכס אחד בלבד. התווית כאן נקבעת מנקודת המבט של הישות הראשונה: נכס מכיל חדר, אך חדר אינו מכיל נכס. מנקודת המבט של הישות השנייה, ניתן בדרך כלל להסיק בקלות את התווית המקבילה.
רק החלק first-entity הוא חובה. הדבר מאפשר להציג ישויות ללא יחסים, דבר שימושי מאוד בעת בניית תרשים באופן איטרטיבי. אם מצוינים חלקים אחרים בהצהרה, כל החלקים הם חובה.
טקסט Unicode
שמות ישויות, יחסים ותכונות תומכים כולם בטקסט unicode.
העתק
הטמעה
erDiagram
"This ❤ Unicode"
תחביר יחסים
ניתן לפצל את חלק היחס בכל הצהרה לשלושה תת-חלקים:
- הקרדינליות של הישות הראשונה ביחס לישות השנייה
- האם היחס מקנה זהות לישות הבת
- הקרדינליות של הישות השנייה ביחס לישות הראשונה
קרדינליות היא מאפיין המתאר את מספר האלמנטים שיכולים להיות משויכים לישות המעורבת. בדוגמה שלעיל, PROPERTY אחד יכול להיות משויך למופע ROOM אחד או יותר, ואילו ROOM אחד יכול להיות משויך ל-PROPERTY אחד בלבד. בכל סימן קרדינליות יש שני תווים: התו החיצוני ביותר מייצג את המקסימום, והתו הפנימי ביותר מייצג את המינימום. הטבלה שלהלן מסכמת את אפשרויות הקרדינליות:
| ערך (שמאל) | ערך (ימין) | משמעות |
|---|---|---|
| |o | o| | אפס או אחד |
| || | || | בדיוק אחד |
| }o | o{ | אפס או יותר (ללא הגבלה) |
| }| | |{ | אחד או יותר (ללא הגבלה) |
| ערך (שמאל) | ערך (ימין) | משמעות |
|---|---|---|
| one or zero | one or zero | אפס או אחד |
| zero or one | zero or one | אפס או אחד |
| one or more | one or more | אחד או יותר |
| one or many | one or many | אחד או יותר |
| many(1) | many(1) | אחד או יותר |
| 1+ | 1+ | אחד או יותר |
| zero or more | zero or more | אפס או יותר |
| zero or many | zero or many | אפס או יותר |
| many(0) | many(0) | אפס או יותר |
| 0+ | 0+ | אפס או יותר |
| only one | only one | בדיוק אחד |
| 1 | 1 | בדיוק אחד |
זיהוי
יחסים יכולים להיות מזוהים או בלתי מזוהים, והם מרונדרים בקו מלא או מקווקו בהתאמה. הדבר חשוב כאשר אחת הישויות אינה יכולה להתקיים באופן עצמאי ללא האחרת. לדוגמה, חברה המספקת ביטוח לנהיגה ברכב עשויה להזדקק לאחסון נתוני NAMED-DRIVER. בעת המידול, אנו עשויים להבחין תחילה ש-CAR אחד יכול להיות מונהג על ידי PERSON-ים רבים, ו-PERSON אחד יכול לנהוג ב-CAR-ים רבים; שניהם יכולים להתקיים ללא האחר, ולכן זהו יחס בלתי מזוהה, שאותו נוכל לציין ב-Mermaid כ: PERSON }|..|{ CAR : "driver". שימו לב לשתי הנקודות שבאמצע היחס, שיגרמו לציור קו מקווקו בין שתי הישויות. אולם כאשר יחס רבים-לרבים זה מפורק לשני יחסי אחד-לרבים, אנו מבחינים שללא PERSON ו-CAR, NAMED-DRIVER לא יכול להתקיים. יחסים אלו הופכים ליחסים מזוהים, ומיוצגים במקף, כלומר בקו מלא:
| ערך | כינוי |
|---|---|
| -- | מזהה |
| .. | בלתי מזהה |
| ערך | 别名为 |
|---|---|
| to | מזהה |
| optionally to | בלתי מזהה |
העתק
הטמעה
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
PERSON }o..o{ NAMED-DRIVER : is
העתק
הטמעה
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
PERSON }o--o{ NAMED-DRIVER : is
תכונה
ניתן להגדיר תכונות לישות על ידי ציון שם הישות, ולאחריו בלוק המכיל מספר שמות type, כאשר הבלוק תחום בסוגריים מסולסלים {}. התכונות מוצגות בתוך תיבת הישות, לדוגמה:
העתק
הטמעה
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
CAR {
string registrationNumber
string make
string model
}
PERSON ||--o{ NAMED-DRIVER : is
PERSON {
string firstName
string lastName
int age
}
ערך ה-type חייב להתחיל בתו אות, ויכול להכיל ספרות, מקפים, קווים תחתונים, סוגריים עגולים וסוגריים מרובעים. ערך ה-name עוקב אחר פורמט דומה לזה של type, אך יכול גם להתחיל בכוכבית, כאפשרות נוספת לציון שהתכונה היא מפתח ראשי. מעבר לכך, אין הגבלות נוספות, ואין קבוצה מוגדרת של סוגי נתונים חוקיים.
כינוי ישות
ניתן להוסיף כינוי לישות באמצעות סוגריים מרובעים. אם סופק כינוי, התרשים יציג את הכינוי במקום את שם הישות, והכינוי כפוף לכל אותם כללים החלים על שם הישות.
העתק
הטמעה
erDiagram
p[Person] {
string firstName
string lastName
}
a["Customer Account"] {
string email
}
p ||--o| a : has
מפתחות תכונה והערות
ניתן גם להגדיר לתכונה מפתח או הערה. המפתח יכול להיות מפתח ראשי (PK), מפתח זר (FK) או מפתח ייחודי (UK). כדי לציין מספר אילוצי מפתח בתכונה אחת, יש להפריד ביניהם בפסיקים (לדוגמה, PK, FK). ההערה מוגדרת באמצעות מרכאות כפולות בסוף התכונה, וההערה לא יכולה להכיל תו מרכאות כפולות.
העתק
הטמעה
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
CAR {
string registrationNumber PK
string make
string model
string[] parts
}
PERSON ||--o{ NAMED-DRIVER : is
PERSON {
string driversLicense PK "The license #"
string(99) firstName "Only 99 characters are allowed"
string lastName
string phone UK
int age
}
NAMED-DRIVER {
string carRegistrationNumber PK, FK
string driverLicence PK, FK
}
MANUFACTURER ||--o{ CAR : makes
כיוון
הצהרת הכיוון מצהירה על כיוון התרשים.
TB מצהיר שכיוון התרשים הוא מלמעלה למטה, ו-BT יכול להפוך אותו למלמטה למעלה.
העתק
הטמעה
erDiagram
direction TB
CUSTOMER ||--o{ ORDER : places
CUSTOMER {
string name
string custNumber
string sector
}
ORDER ||--|{ LINE-ITEM : contains
ORDER {
int orderNumber
string deliveryAddress
}
LINE-ITEM {
string productCode
int quantity
float pricePerUnit
}
LR מצהיר שכיוון התרשים הוא משמאל לימין, ו-RL יכול להפוך אותו למימין לשמאל.
העתק
הטמעה
erDiagram
direction LR
CUSTOMER ||--o{ ORDER : places
CUSTOMER {
string name
string custNumber
string sector
}
ORDER ||--|{ LINE-ITEM : contains
ORDER {
int orderNumber
string deliveryAddress
}
LINE-ITEM {
string productCode
int quantity
float pricePerUnit
}
הגדרת סגנון צומת
ניתן להחיל סגנון מסוים על צומת, כגון מסגרת עבה יותר או צבע רקע שונה.
העתק
הטמעה
erDiagram
id1||--||id2 : label
style id1 fill:pink,stroke:yellow,stroke-width:4px
style id2 fill:#69d,stroke:#f96,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
ניתן גם לצרף סגנון לרשימת צמתים בהצהרה אחת:
העתק
הטמעה
style nodeId1,nodeId2 styleList
מחלקה
נוח יותר מלהגדיר סגנון בכל פעם הוא להגדיר מחלקת סגנון ולצרף אותה לצמתים הזקוקים למראה שונה.
הגדרת מחלקה מוצגת בדוגמה שלהלן:
העתק
הטמעה
classDef className fill:pink,stroke:#333,stroke-width:4px
ניתן גם להגדיר מספר מחלקות בהצהרה אחת:
העתק
הטמעה
classDef firstClassName,secondClassName font-size:12pt
התחביר לצירוף מחלקה לצומת הוא כדלקמן:
העתק
הטמעה
class nodeId1 className
ניתן גם לצרף מחלקה לרשימת צמתים בהצהרה אחת:
העתק
הטמעה
class nodeId1,nodeId2 className
ניתן גם לצרף מספר מחלקות בו-זמנית:
העתק
הטמעה
class nodeId1,nodeId2 className1,className2
דרך נוחה להוספת מחלקה היא להשתמש באופרטור ::: כדי לצרף שם מחלקה לצומת, כפי שמוצג להלן:
העתק
הטמעה
erDiagram
direction TB
CAR:::someclass {
string registrationNumber
string make
string model
}
PERSON:::someclass {
string firstName
string lastName
int age
}
HOUSE:::someclass
classDef someclass fill:#f96
ניתן להצהיר על היחסים בין ישויות באמצעות התחביר שלהלן:
העתק
הטמעה
erDiagram
CAR {
string registrationNumber
string make
string model
}
PERSON {
string firstName
string lastName
int age
}
PERSON:::foo ||--|| CAR : owns
PERSON o{--|| HOUSE:::bar : has
classDef foo stroke:#f00
classDef bar stroke:#0f0
classDef foobar stroke:#00f
בדומה להצהרת class, גם תחביר הקיצור יכול להחיל מספר מחלקות בבת אחת:
העתק
הטמעה
nodeId:::className1,className2
מחלקת ברירת מחדל
אם מחלקה נקראת default, היא תוקצה לכל המחלקות ללא הגדרת מחלקה ספציפית.
העתק
הטמעה
classDef default fill:pink,stroke:#333,stroke-width:4px;
שים לב: לסגנון מותאם אישית מסגנון או מהצהרות מחלקה אחרות יש עדיפות, והוא עוקף את סגנון ברירת המחדל. (לדוגמה, מחלקת default מגדירה רקע ורוד לצומת, אך אם מחילים מחלקת blue, הצומת יקבל צבע רקע כחול.)
העתק
הטמעה
erDiagram
CAR {
string registrationNumber
string make
string model
}
PERSON {
string firstName
string lastName
int age
}
PERSON:::foo ||--|| CAR : owns
PERSON o{--|| HOUSE:::bar : has
classDef default fill:pink,stroke-width:4px
classDef foo stroke:#f90
classDef bar stroke:#ff0
classDef foobar stroke:#69f
תצורה
פריסה
פריסת התרשים מטופלת על ידי render(); פריסת ברירת המחדל היא פריסת ELK, המתאימה לתרשימים גדולים ומורכבים יותר.
כדי לעבור לפריסת Dagre הקלאסית, ניתן להגדיר זאת ב-config שב-YAML frontmatter
העתק
הטמעה
---
config:
layout: dagre
---
תוכן קוד Mermaid הוא כדלקמן:
העתק
הטמעה
---
title: Order example
config:
layout: elk
---
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
CUSTOMER }|..|{ DELIVERY-ADDRESS : uses