محتويات الدورة

MariaDB / الأساسي: الأسس العلاقية / الدرس 3

المفاتيح والتكامل العلاقي

نمذج العملاء والحجوزات بهويات وعلاقات صحيحة، واجعل القيود تعبر عن القواعد بدلاً من إصلاح التناقضات لاحقاً.

وقت القراءة التقريبي: 4 دقيقةتاريخ مراجعة المحتوى
في هذه الصفحة

أهداف الدرس

  • تمييز المفاتيح الأساسية والفريدة والخارجية.
  • اختيار إجراءات التكامل المرجعي بوعي.

الهوية مستقرة وقد يتغير الاسم

يعطي المفتاح الأساسي كل صف هوية فريدة غير NULL. وقد يحتاج الرمز التجاري إلى UNIQUE حتى مع وجود مفتاح عددي. لا تصلح أسماء العملاء مفاتيح لأن الأسماء مشتركة وقابلة للتغيير. يفرض المفتاح الخارجي وجود الأصل الذي يشير إليه الفرع. يبقي التطبيع بريد العميل في مكان مرجعي واحد بدلاً من نسخه إلى كل حجز ثم ظهور نسخ متناقضة عند التعديل.

اكتب تعريف المفتاح الخارجي كاملاً

يستخدم عمودا العلاقة النوع العددي نفسه والإشارة نفسها، ويستخدم الجدولان InnoDB صراحة. يجعل تعريف FOREIGN KEY على مستوى الجدول العلاقة واضحة ويتجنب سلوك اختصار REFERENCES في إصدارات MariaDB القديمة. المفتاح الأساسي للأصل مفهرس، ويحتاج الفرع فهرساً مناسباً قد ينشئه InnoDB تلقائياً. يمنع تقييد حذف الأصل فقدان العميل ما دام الحجز يحتاجه.

sql SQL توضيحي؛ النتائج المتوقعة مستنتجة وليست قياسات.
CREATE TABLE customers (
 customer_id INT PRIMARY KEY,
 email VARCHAR(120) NOT NULL UNIQUE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE bookings (
 booking_id INT PRIMARY KEY, customer_id INT NOT NULL,
 CONSTRAINT fk_booking_customer FOREIGN KEY (customer_id)
 REFERENCES customers(customer_id) ON DELETE RESTRICT
) ENGINE=InnoDB;

يحل قيد البريد والعلاقة مشكلتين مختلفتين، ولا يغني أي منهما عن المفاتيح الأساسية.

إجراءات المرجعية تحدد العواقب

يرفض RESTRICT تغيير الأصل إذا ترك فروعاً غير صالحة. وينقل CASCADE حذف الأصل أو تحديث مفتاحه إلى الفروع وقد يمس صفوفاً كثيرة. يحتاج SET NULL عموداً يقبل NULL ويعني أن غياب العلاقة مقبول. اختر وفق معنى العمل لا سهولة الاستيراد. يسمح المفتاح الخارجي القابل للفراغ بقيمة NULL دون أصل مطابق؛ استخدم NOT NULL عندما يلزم عميل لكل حجز.

اقرأ علاقة مصغرة صحيحة

ابدأ بالأصل ثم الفرع في الجدولين الفارغين من التعريف السابق. يعيد الربط حجزاً واحداً مع البريد الحالي. يجوز حجز ثان للعميل 7 لأن مفتاح الفرع الخارجي غير فريد. أما إعادة booking_id بالقيمة 101 فتخالف المفتاح الأساسي، والإشارة للعميل 99 تخالف العلاقة. هذه فحوص مختلفة، لذا احتفظ برمز الخطأ بدلاً من تسمية كل رفض تكراراً.

sql SQL توضيحي؛ النتائج المتوقعة مستنتجة وليست قياسات.
INSERT INTO customers VALUES (7, 'sara@example.test');
INSERT INTO bookings VALUES (101, 7);
SELECT b.booking_id, c.email
FROM bookings AS b JOIN customers AS c
 ON c.customer_id = b.customer_id
ORDER BY b.booking_id;
الناتج المتوقع
booking_id | email
101        | sara@example.test

نتيجة متوقعة للإضافتين؛ لا تستخدم بيانات شخصية حقيقية.

حافظ على القيود أثناء التغيير

افحص SHOW CREATE TABLE عند سلوك غير متوقع للقيد. حمّل الأصول قبل الفروع أو استخدم مرحلة تجهيز للتحقق. قد يسمح تعطيل foreign_key_checks بسجلات يتيمة، ولا تثبت إعادة تفعيله صحة الصفوف السابقة. راجعها باستعلام استبعاد بعد الترحيل المنضبط وأصلح مطابقة المصدر. يتبع التفرد أيضاً قواعد الترتيب اللغوي، وقد يحتوي فهرس UNIQUE في MariaDB عدة قيم NULL إذا سمح العمود بها.

الأخطاء الشائعة وإصلاحها

ERROR 1452: Cannot add or update a child row

لماذا يحدث؟
يشير الفرع إلى أصل غير موجود.
كيف تصلحه؟
صحح المعرف أو أضف الأصل الصحيح أولاً.
كيف تتجنب تكراره؟
تحقق من مطابقة المعرفات وحمّل الاعتماديات بالترتيب.

ERROR 1062: Duplicate entry

لماذا يحدث؟
توجد قيمة أساسية أو فريدة مساوية وفق قواعد المقارنة.
كيف تصلحه؟
حدد المفتاح المذكور وقرر هل هي إعادة محاولة أم بيانات متعارضة.
كيف تتجنب تكراره؟
حدد سلوك إعادة المحاولة وتوحيد البريد بوضوح.

ERROR 1005: Cannot create table; errno 150

لماذا يحدث؟
قد تختلف أنواع المفتاح الخارجي أو المحركات أو فهارس الأصل.
كيف تصلحه؟
قارن التعريفات الفعلية وافحص تشخيص InnoDB التفصيلي.
كيف تتجنب تكراره؟
صرح بأنواع متطابقة وقيود كاملة مسماة في ترحيلات مراجعة.

اختبر فهمك

1. يمكن للعميل امتلاك حجوزات كثيرة. هل تجعل bookings.customer_id فريداً؟

اعرض الحل المشروح

لا؛ سيقصر التفرد العميل على حجز غير فارغ واحد. أبقِ booking_id مفتاحاً أساسياً وcustomer_id مفتاحاً خارجياً غير فارغ، واستخدم فهرساً غير فريد للبحث. يظل معرف الأصل فريداً، لذلك يشير كل حجز إلى عميل واحد.

2. عطّل استيراد قديم القيود. اكتشف الحجوزات اليتيمة دون حذف شيء.

اعرض الحل المشروح

اربط الحجوزات بالعملاء ربطاً يسارياً واختر الصفوف التي يكون مفتاح الأصل فيها NULL. مع مفتاح فرع غير فارغ، كل نتيجة سجل يتيم يحتاج التحقيق. تكون النتيجة فارغة للعينة الصحيحة، ولا تثبت صحة قيود أخرى كالبريد الفريد.

sql حل محلول وفق الافتراضات الاصطناعية المحددة.
SELECT b.booking_id FROM bookings AS b
LEFT JOIN customers AS c ON c.customer_id = b.customer_id
WHERE c.customer_id IS NULL;

أهم ما تعلمته

  • يعبر المفتاح عن الهوية، والمفتاح الخارجي عن العلاقة.
  • اختر الانتشار وفق العواقب التي يقبلها العمل.

المراجع الرسمية