طَبِّقْهاتعلّم المبدأ، وطبّقه بيدكمقرر 121 · مبادئ قواعد البيانات
الدرس 11 · الوحدة 5: تصميم الجداول والعلاقات

من المخطط إلى الجداول

نحوّل المخطط إلى أوامر CREATE TABLE بقواعد ثابتة. ⏱ نحو 30 دقيقة.

بعد هذا الدرس ستستطيع أن:
  • تطبّق قواعد تحويل المخطط إلى جداول.
  • تنفّذ علاقات 1:N و 1:1 و M:N بالمفاتيح والقيود.
  • تعالج الخاصية المتعددة القيم بجدول مستقل.
  • تنشئ الجداول وتدخل البيانات بالترتيب الصحيح.

١قواعد التحويل

المخطط جاهز؛ والتحويل إلى جداول يتبع قواعد ثابتة لا اجتهاد فيها:

في المخططفي القاعدة
كيانجدول، اسمه جمع بالإنجليزية.
خاصية بسيطةعمود بنوع مناسب.
خاصية مفتاحPRIMARY KEY
خاصية إلزاميةNOT NULL
علاقة 1:Nمفتاح أجنبي في جدول «المتعدد».
علاقة 1:1مفتاح أجنبي UNIQUE في أحد الجدولين.
علاقة M:Nجدول وسيط بمفتاحين أجنبيين يكوّنان معًا المفتاح الأساسي.
خاصية متعددة القيمجدول مستقل: المفتاح الأجنبي + القيمة.
خاصية مشتقةلا عمود لها؛ تُحسب في الاستعلام.

٢مثال كامل: عيادة الأسنان

هذا حل تحدي الدرس 7 بعد إضافة العلاقات:

patientsالمرضىidPKnamephonebirth_dateappointmentsالمواعيدidPKpatient_idFKdoctor_idFKappt_dateappt_timereasondoctorsالأطباءidPKnamespecialty
مخطط العيادة: المريض له صفر أو أكثر من المواعيد، والطبيب كذلك، والموعد لمريض واحد عند طبيب واحد.

نطبّق القواعد: ثلاثة كيانات تصير ثلاثة جداول، والعلاقتان 1:N تصيران مفتاحين أجنبيين في appointments. وأضفنا قاعدة عمل مهمة: الطبيب لا يُحجز له موعدان في الوقت نفسه:

query.sql
CREATE TABLE patients (  id         INTEGER PRIMARY KEY,  name       TEXT NOT NULL,  phone      TEXT UNIQUE,  birth_date TEXT);CREATE TABLE doctors (  id        INTEGER PRIMARY KEY,  name      TEXT NOT NULL,  specialty TEXT NOT NULL);CREATE TABLE appointments (  id         INTEGER PRIMARY KEY,  patient_id INTEGER NOT NULL REFERENCES patients(id),  doctor_id  INTEGER NOT NULL REFERENCES doctors(id),  appt_date  TEXT NOT NULL,  appt_time  TEXT NOT NULL,  reason     TEXT,  UNIQUE (doctor_id, appt_date, appt_time));INSERT INTO patients VALUES (1, 'منى السهلي', '0560000001', '1998-04-02'), (2, 'وليد الرحيلي', '0560000002', '1985-11-20');INSERT INTO doctors VALUES (1, 'د. هالة', 'تقويم'), (2, 'د. عماد', 'علاج عصب');INSERT INTO appointments VALUES (1, 1, 1, '2025-06-01', '09:00', 'تركيب تقويم'), (2, 2, 2, '2025-06-01', '10:30', 'ألم ضرس'), (3, 1, 1, '2025-06-15', '09:00', 'متابعة'); -- مواعيد المريضة منىSELECT appt_date, appt_time, reasonFROM appointmentsWHERE patient_id = 1;
النتيجة · صفّان
appt_dateappt_timereason
2025-06-0109:00تركيب تقويم
2025-06-1509:00متابعة
query.sql
CREATE TABLE patients (  id         INTEGER PRIMARY KEY,  name       TEXT NOT NULL,  phone      TEXT UNIQUE,  birth_date TEXT);CREATE TABLE doctors (  id        INTEGER PRIMARY KEY,  name      TEXT NOT NULL,  specialty TEXT NOT NULL);CREATE TABLE appointments (  id         INTEGER PRIMARY KEY,  patient_id INTEGER NOT NULL REFERENCES patients(id),  doctor_id  INTEGER NOT NULL REFERENCES doctors(id),  appt_date  TEXT NOT NULL,  appt_time  TEXT NOT NULL,  reason     TEXT,  UNIQUE (doctor_id, appt_date, appt_time));INSERT INTO patients VALUES (1, 'منى السهلي', '0560000001', '1998-04-02'), (2, 'وليد الرحيلي', '0560000002', '1985-11-20');INSERT INTO doctors VALUES (1, 'د. هالة', 'تقويم'), (2, 'د. عماد', 'علاج عصب');INSERT INTO appointments VALUES (1, 1, 1, '2025-06-01', '09:00', 'تركيب تقويم'), (2, 2, 2, '2025-06-01', '10:30', 'ألم ضرس'), (3, 1, 1, '2025-06-15', '09:00', 'متابعة'); -- حجز مزدوج عند د. هالةINSERT INTO appointments VALUES (4, 2, 1, '2025-06-01', '09:00', 'تنظيف');
✓ أُضيف 3 صفوف
✗ خطأ (السطر 28): مخالفة قيد UNIQUE: القيمة مكررة في appointments.doctor_id, appointments.appt_date, appointments.appt_time

القيد UNIQUE (doctor_id, appt_date, appt_time) منع الحجز المزدوج. القيود تحرس قواعد العمل أيضًا.

٣الخاصية المتعددة القيم: جدول مستقل

للمريض أكثر من رقم جوال؟ لا نضيف phone2 و phone3، بل جدولًا جديدًا كل صف فيه رقم واحد:

✗ أعمدة مكررة
query.sql
CREATE TABLE patients (  id     INTEGER PRIMARY KEY,  name   TEXT,  phone1 TEXT,  phone2 TEXT,  phone3 TEXT   -- والرابع؟);
✓ جدول مستقل
query.sql
CREATE TABLE patient_phones (  patient_id INTEGER REFERENCES patients(id),  phone      TEXT,  PRIMARY KEY (patient_id, phone));

مع الأعمدة المكررة: كيف تبحث عن رقم؟ في ثلاثة أعمدة! ومريض له رقم واحد يترك عمودين فارغين. أما الجدول المستقل فيقبل أي عدد، والبحث في عمود واحد.

٤علاقة 1:1

لكل موظف سيارة واحدة على الأكثر من سيارات الشركة، ولكل سيارة موظف واحد. نضع المفتاح الأجنبي في جدول السيارات مع UNIQUE:

query.sql
CREATE TABLE employees (id INTEGER PRIMARY KEY, name TEXT);CREATE TABLE cars (  plate       TEXT PRIMARY KEY,  model       TEXT,  employee_id INTEGER UNIQUE REFERENCES employees(id));INSERT INTO employees VALUES (1, 'سامي'), (2, 'هاني');INSERT INTO cars VALUES ('أ ب ج 1234', 'كامري', 1);INSERT INTO cars VALUES ('د هـ و 5678', 'سوناتا', 1);
✓ أُضيف صف واحد
✗ خطأ (السطر 9): مخالفة قيد UNIQUE: القيمة مكررة في cars.employee_id

UNIQUE منعت سيارة ثانية لسامي، فبقيت العلاقة 1:1.

٥ترتيب التنفيذ

  1. أنشئ الجداول المستقلة أولًا (التي لا مفاتيح أجنبية فيها): المرضى والأطباء.
  2. ثم الجداول التي تشير إليها: المواعيد.
  3. ثم أدخل البيانات بالترتيب نفسه: الآباء قبل الأبناء.
  4. وعند الحذف: العكس، الأبناء قبل الآباء.

توقّع وتحقّق

علاقة 1:1 تُنفَّذ بمفتاح أجنبي مع:

لا يتكرر.

خاصية متعددة القيم تصير:

صف لكل قيمة.

أي جدول يُنشأ أولًا في العيادة؟

الأب قبل الابن.

منع موعدين لطبيب في الوقت نفسه:

قيد فريد مركّب.

الخلاصة

تحدٍّ برمجي: نفّذ مخطط المكتبة

صعب

حوّل مخطط المكتبة (تحدي الدرس 8) إلى جداول: الأعضاء والكتب والإعارات.

المطلوب:
  • members: id مفتاح، name إلزامي، phone لا يتكرر.
  • books: isbn مفتاح نصي، title إلزامي.
  • loans: id مفتاح، member_id و isbn مفتاحان أجنبيان إلزاميان، loan_date إلزامي، return_date اختياري.
👀 اعرض النتيجة المطلوبة
✓ التحقق الآلي من حلّك:
  • الكود يعمل بلا أخطاء
  • يقبل عضوًا وكتابًا
  • يقبل إعارة بلا تاريخ إرجاع
  • يرفض إعارة لعضو غير موجود
  • يرفض إعارة لكتاب غير موجود
  • يرفض إعارة بلا تاريخ
  • يرفض جوالًا مكررًا

💡 تلميح 1
أنشئ members و books أولًا، ثم loans.
💡 تلميح 2
isbn TEXT NOT NULL REFERENCES books(isbn)

حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.

solution.sql
CREATE TABLE members (  id    INTEGER PRIMARY KEY,  name  TEXT NOT NULL,  phone TEXT UNIQUE);CREATE TABLE books (  isbn  TEXT PRIMARY KEY,  title TEXT NOT NULL);CREATE TABLE loans (  id          INTEGER PRIMARY KEY,  member_id   INTEGER NOT NULL REFERENCES members(id),  isbn        TEXT NOT NULL REFERENCES books(isbn),  loan_date   TEXT NOT NULL,  return_date TEXT);
انتقل إلى تقييم الدرساختيار من متعدد، وصح وخطأ، وأكمل الفراغ، وتتبّع الناتج.ابدأ التقييم ←

📝 معلم؟ أرسل ملاحظة للمؤلف عن هذا الدرس