محرر مخططات الكيانات بـ Mermaid
يبيّن مخطط الكيان والعلاقة الجداولَ وأعمدتَها وطريقة ارتباط بعضها ببعض. يناسبك حين يكون الموضوع مخطط قاعدة بيانات وتكون الأسئلة المهمة عن المفاتيح والتعدّديات — واحد إلى متعدد، أو اختياري، أو عبر جدول وصل. أما الأنواع ذات السلوك والوراثة فمخطط الأصناف أنسب لها.
مخطط طلبات مطبَّع بجدول وصل
الجزء الجدير بالانتباه هو `}o--||` عند سطر الطلب: فهكذا تُعبَّر علاقة متعدد إلى متعدد تعبيرًا صادقًا، عبر جدول وصل له أعمدته الخاصة، بدل التظاهر بأن جدولين يرتبطان مباشرة. وحفظ السعر في السطر لا في المنتج وحده هو بالضبط نوع القرار الذي ينبغي للمخطط أن يُظهره. ولاحظ أيضًا أن كل تسمية علاقة بين علامتَي اقتباس: وهذا في العربية ليس اختياريًا.
erDiagram
عميل ||--o{ طلب : "يقدّم"
طلب ||--|{ سطر_طلب : "يتكون من"
منتج ||--o{ سطر_طلب : "يظهر في"
عميل ||--o{ عنوان : "يُشحن إلى"
طلب ||--o| فاتورة : "تصدر عنه"
عميل {
int معرف PK
string بريد UK "يُحفظ بأحرف صغيرة"
string اسم
string رقم_ضريبي
datetime تاريخ_الإنشاء
}
طلب {
int معرف PK
int معرف_العميل FK
string حالة
decimal الإجمالي
}
سطر_طلب {
int معرف_الطلب PK, FK
int معرف_المنتج PK, FK
int كمية
decimal سعر "السعر وقت تقديم الطلب"
}
منتج {
int معرف PK
string رمز_الصنف UK
string اسم
}
عنوان {
int معرف PK
int معرف_العميل FK
string رمز_بريدي
}
فاتورة {
int معرف PK
string رقم_الفاتورة UK
decimal ضريبة
}أمثلة مشروحة
١. كيانان وعلاقة واحدة
كل علاقة في مخطط الكيانات تطلب تسمية بعد النقطتين — وهي ليست اختيارية بخلاف حافة مخطط التدفق. وتُقرأ كجملة: عميل يقدّم طلبًا.
erDiagram
عميل ||--o{ طلب : "يقدّم"٢. إضافة الأعمدة
كل سطر خاصية على صورة `نوع اسم` وكلا الجزأين إلزامي. والرموز `PK` و`FK` و`UK` تؤشّر المفاتيح؛ والنص بين علامتَي اقتباس في النهاية تعليق على العمود.
erDiagram
عميل ||--o{ طلب : "يقدّم"
عميل {
int معرف PK
string بريد UK
string اسم
}
طلب {
int معرف PK
int معرف_العميل FK
datetime تاريخ_التقديم "بتوقيت UTC"
}٣. تعدّدية تقول شيئًا
الرمزان الأقرب إلى كل كيان هما تعدّديته. ويقول هذا المثال إن الطلب يجب أن يكون له سطر واحد على الأقل، بينما قد لا يكون للعميل أي طلب: وهو قيد حقيقي ينبغي للمخطط أن يفرضه وللرسم أن يُظهره.
erDiagram
عميل ||--o{ طلب : "يقدّم"
طلب ||--|{ سطر_طلب : "يتكون من"
سطر_طلب }o--|| منتج : "يشير إلى"٤. متعدد إلى متعدد عبر جدول وصل
يستطيع Mermaid رسم علاقة متعدد إلى متعدد مباشرة، لكنها لا توجد في المخطط الفعلي إلا نادرًا: فتحتها جدول وصل. ورسمه أصدق ويترك موضعًا للأعمدة التي تخص العلاقة نفسها.
erDiagram
طالب ||--o{ تسجيل : "يسجّل في"
مقرر ||--o{ تسجيل : "يُدرّس عبر"
تسجيل {
int معرف_الطالب PK, FK
int معرف_المقرر PK, FK
datetime تاريخ_التسجيل
string تقدير "فارغ حتى الاختبار"
}
طالب {
int معرف PK
string اسم
}
مقرر {
int معرف PK
string رمز UK
}٥. علاقات الكيان بنفسه
قد يرتبط جدول بنفسه: تسلسل إداري، شجرة تصنيفات، سلسلة تعليقات. وتسمية العلاقة هنا أهم من المعتاد، لأن طرفي العلاقة هما الكيان نفسه.
erDiagram
موظف ||--o{ موظف : "يشرف على"
موظف {
int معرف PK
int معرف_المدير FK "فارغ للإدارة العليا"
string اسم
string مسمى_وظيفي
}ملخص صياغة مخطط الكيانات
تُكتب التعدّدية برمزين عند كل طرف من العلاقة وتُقرأ من الداخل إلى الخارج. فالزوج الأيسر يصف الكيان الأيسر، والزوج الأيمن يصف الأيمن.
| الصياغة | المعنى |
|---|---|
| erDiagram | يفتح المخطط. حساس لحالة الأحرف: `erdiagram` لا يعمل. |
| A ||--o{ B : "تسمية" | علاقة. والتسمية إلزامية. |
| || | واحد بالضبط. |
| o| | صفر أو واحد. |
| }| | واحد أو أكثر. |
| }o | صفر أو أكثر. |
| -- | علاقة معرِّفة — خط متصل. |
| .. | علاقة غير معرِّفة — خط متقطع. |
| A { ... } | كتلة خصائص الكيان A. |
| int معرف PK | خاصية: النوع أولًا، ثم الاسم، ثم علامة المفتاح إن وُجدت. |
| PK / FK / UK | مفتاح أساسي، أجنبي، فريد. |
| int معرف PK, FK | عدة علامات مفاتيح تفصلها فاصلة. |
| string بريد "تعليق" | النص بين علامتَي اقتباس في النهاية تعليق على العمود. |
| A ||--o{ B : "ينتمي إلى" | علامتا الاقتباس إلزاميتان بمجرد أن تحتوي التسمية على مسافة. وبدونهما تُقتطع التسمية عند أول مسافة وتصير كل كلمة باقية كيانًا وهميًا. |
الأخطاء الستة التي تُفسد مخطط الكيانات
مخطط الكيانات أشد الأنواع الستة صرامةً في صياغته: فما يمرّ في المخططات الأخرى يُرفض هنا صراحةً. لكن فيه أيضًا خطأً صامتًا يقع فيه من يكتب بالعربية بيسر خاص. وكل ما هنا أُعيد إنتاجه على Mermaid 11.12.2.
ما تراه
يُرسم المخطط، والتسمية مقتطعة، وتظهر كيانات لم تكتبها
لماذا
تسمية العلاقة فيها مسافة وليست بين علامتَي اقتباس. وهذا أكثر ما سيعترضك في العربية، لأن عبارات العلاقة عندنا تكاد تكون دائمًا من عدة كلمات: «ينتمي إلى»، «يظهر في»، «يُشحن إلى». قِيس: `عميل ||--o{ طلب : ينتمي إلى` لا يبلّغ عن أي خطأ، بل يختصر التسمية إلى «ينتمي» وينشئ كيانًا فارغًا اسمه «إلى». ومع ثلاث كلمات يولد كيانان وهميان. فيُرسم جدولان في صورة أربعة مستطيلات ولا شيء ينبّهك — سوى أن الإطار يقفز من 128 إلى 356 بكسل.
الحل
ضع بين علامتَي اقتباس كل تسمية فيها مسافة. وهذا في العربية يعني كل تسمية عمليًا؛ واتخاذه قاعدة أيسر من الترجيح في كل مرة.
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'
لماذا
خاصية لها اسم وليس لها نوع. فخصائص مخطط الكيانات تُكتب `نوع اسم`، والنوع ليس اختياريًا — وهذا يفاجئ القادمين من قواعد البيانات بلا مخطط.
الحل
امنح كل خاصية نوعًا. واختلقه إن لم يكن في المخطط الفعلي: `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، وهي النسخة التي يستعملها هذا الموقع.
التخطيط تمليه العلاقات لا عدد الكيانات
سلسلة كيانات يرتبط كل منها بالذي يليه تُرسم عمودًا مرتفعًا: فأربعون كيانًا تعطي إطارًا يقارب 116×7315، مقابل 116×470 عند ثلاثة. لكن الأربعين نفسها إذا ارتبطت كلها بجدول مركزي واحد أعطت شيئًا أعرض بكثير وأقصر. وهذا هو النوع الوحيد هنا الذي يغيّر فيه شكلُ بياناتك شكلَ الصورة أكثر مما يغيّر حجمها، فالمخطط الذي لا يتسع يُصلَح غالبًا بتغيير أيّ العلاقات ترسم لا بتغيير عددها.
في العربية تحتاج كل تسمية تقريبًا إلى علامتَي اقتباس
يستحق هذا التكرار، لأنه أغلى خطأ صامت في هذه الصفحة. فتسميات العلاقات الإنجليزية قد تكون كلمة واحدة — places وcontains وreferences — ولذلك تبدو علامتا الاقتباس في التوثيق الإنجليزي زينة. أما في العربية فأغلبها عبارات من عدة كلمات وتتفكك بدون علامتَي الاقتباس. والقاعدة العملية: ضع التسمية دائمًا بين علامتَي اقتباس وكفّ عن التفكير في الأمر.
أسماء الكيانات معرّفات، فاختر أسلوبًا والزمه
الأسماء العربية تعمل أسماءَ كيانات وأعمدة دون مشكلة — جُرّب `عميل` و`طلب` و`منتج`. لكن اسم الكيان معرّف، فالمسافة ممنوعة فيه: اختر الشرطة السفلية مثل `سطر_طلب` أو الوصل، ثم الزم اختيارك في المخطط كله. ولا يفرض Mermaid أي عرف هنا، لكن خلط الأسلوبين يولّد كيانين متمايزين دون أي تحذير، تمامًا كما يفعل خلط الأحرف الكبيرة والصغيرة في اللاتينية.
الصياغة أشد صرامة من الأنواع الستة كلها
تسميات العلاقات إلزامية، وأنواع الخصائص كذلك، ورموز التعدّدية تكوّن مجموعة مغلقة. وبالمقارنة مع جانت، حيث يُرسم كل شيء تقريبًا وتصمت الأخطاء، يسقط مخطط الكيانات مبكرًا وبصوت عالٍ. وهذه ميزة: فإن رُسم مخطط كيانات فالأرجح كثيرًا أنه المخطط الذي قصدته — باستثناء واضح هو التسميات بلا علامتَي اقتباس.
التسميات HTML، فتصدير PNG يعيد الرسم
تُرسم جداول خصائص الكيانات داخل `<foreignObject>` في ملف SVG، فلا تستطيع المتصفحات تحويلها مباشرة إلى صورة نقطية على لوحة canvas. وكان تصدير PNG في هذا الموقع يعيد ملف SVG بصمت؛ أما الآن فيعيد رسم المخطط أولًا بتسميات نصية SVG صِرفة وينتج ملف PNG صحيحًا بحجمه الكامل، بتنضيد يختلف اختلافًا بالكاد يُلحظ.
متى يكون مخطط آخر أنسب
إن كنت تحتاج وراثة أو واجهات أو دوالّ فهذا هو المخطط الخاطئ: فمخطط الكيانات لا يعرف شيئًا من هذه المفاهيم. استعمل مخطط الأصناف واقبل أنه ينمذج شيفرتك لا جداولك.
وإن كان المخطط كبيرًا، فمخطط كيانات للمخطط كله يصير ملصقًا جداريًا لا يقرؤه أحد. ارسم الجداول الخمسة التي تمسّ ما تشرحه في تلك اللحظة واترك الباقي خارج الإطار؛ فالمخطط حجة لا جرد.
وإن كان السؤال الحقيقي كيف تتدفق البيانات بين الأنظمة لا كيف تُخزَّن، فالذي يجيب عنه مخطط تدفق فيه مجموعة فرعية لكل نظام، لا مخطط الكيانات.
أنواع المخططات الأخرى
بقلم Dominik Malsch · آخر تحديث: