Register
Process Type
Graphical expression
Mind Type
Structured expression
Note Type
Efficient expression

مخطط ERالصيغة

مخطط ER

يصف مخطط الكيانات والعلاقات (ويُختصر ER diagram) الأشياء المترابطة التي تهمّ مجالًا معرفيًا معيّنًا. ويتكوّن مخطط 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 name ، حيث تُحاط الكتلة بالأقواس المعقوصة {}. وتُعرض الخصائص داخل مربع الكيان، على سبيل المثال:

كود
                            
نسخ
تضمين
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