حل مشكلة المفتاح الخارجي المتعدد في MySQL: دليل خطوة بخطوة

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

المشكلة

تخيل أن لديك جدول SHIPPING_DETAILS المسؤول عن تتبع كل من موردي الشحن (مثل فيديكس أو يو بي إس) وموردي معالجة المنتجات (فكر في Dunder Mifflin). في هذه الحالة، تحتاج عدة أعمدة ضمن تفاصيل الشحن للإشارة إلى نفس الجدول الأب، وهو VENDOR. ومع ذلك، قد تنشأ مشاكل عندما تحاول إنشاء قيود المفتاح الخارجي لهذه الأعمدة، مثل عدم القدرة على تعريف مفاتيح خارجية متعددة.

غالبًا ما يواجه المستخدمون أخطاء مثل:

لا يمكن إنشاء الجدول './<DB_NAME>/SHIPPING_GRID.frm' (خطاء: 150)

تكون هذه الخطأ عادةً إشارة إلى وجود مشكلة في تعريف المفتاح الخارجي أو أنواع البيانات المعنية.

نظرة عامة على الحل

للحل مشكلة تعريف المفاتيح الخارجية المتعددة في MySQL، اتبع هذه الخطوات:

  1. تعريف هيكل الجدول بشكل صحيح: تأكد من أن جدول VENDOR يحتوي على مفتاح أساسي فريد يتوافق مع أعمدة المفتاح الخارجي في جدول SHIPPING_DETAILS.

  2. تصحيح نوع الجدول: تأكد من أن كلا الجدولين (VENDOR و SHIPPING_GRID) من نوع InnoDB. هذا أمر حاسم حيث أن قيود المفاتيح الخارجية غير مدعومة في محركات التخزين الأخرى مثل MyISAM.

  3. ضمان توافق نوع البيانات: تحقق من أن أنواع البيانات لمفاتيح الخارج تتطابق مع نوع البيانات للمفتاح الأساسي الذي تشير إليه. على سبيل المثال، إذا كان VENDOR.no محددًا كـ INT(6)، يجب أن تكون جميع الإشارات للمفاتيح الخارجية بنفس النوع.

  4. تجنب تعريفات المفتاح الأساسي المكررة: تأكد من أن عبارة SQL الخاصة بك لا تتضمن عرضاً غير مقصود لتعريفات متعددة للمفتاح الأساسي. ذلك يمكن أن يؤدي إلى أخطاء أثناء إنشاء الجدول.

مثال على الكود

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

CREATE TABLE SHIPPING_GRID(  
    id INT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'معرف فريد لكل صف',
    shipping_vendor_no INT(6) NOT NULL COMMENT 'مفتاح خارجي إلى VENDOR.no لمورد الشحن (يجب أن يكون vendors_type 3)',
    start_vendor_no INT(6) NOT NULL COMMENT 'مفتاح خارجي إلى VENDOR.no للمورد الذي يتم الشحن منه',
    end_vendor_no INT(6) NOT NULL COMMENT 'مفتاح خارجي إلى VENDOR.no للمورد الذي يتم الشحن إليه',
    shipment_duration INT(1) DEFAULT 1 COMMENT 'مدة الشحن بالأيام الكاملة',
    price FLOAT(5,5) NOT NULL COMMENT 'السعر بالدولار الأمريكي لكل شحنة بالأرطال (حتى 5 أرقام عشرية)',
    is_flat_rate TINYINT(1) DEFAULT 0 COMMENT '1 إذا كانت التكلفة ثابتة بغض النظر عن الوزن، 0 إذا كان السعر بالأرطال',
    INDEX (shipping_vendor_no),
    INDEX (start_vendor_no),
    INDEX (end_vendor_no),
    FOREIGN KEY (shipping_vendor_no) REFERENCES VENDOR (no),
    FOREIGN KEY (start_vendor_no) REFERENCES VENDOR (no),
    FOREIGN KEY (end_vendor_no) REFERENCES VENDOR (no)  
) ENGINE=InnoDB;

النقاط الرئيسية

  • أنواع البيانات مهمة: تأكد دائماً من أن أعمدة المفتاح الخارجي تطابق نوع البيانات للمفتاح الأساسي المشار إليه.
  • استخدم InnoDB: إذا كنت بصدد إعداد مفاتيح خارجية عبر الجداول، فإن استخدام محرك InnoDB أمر ضروري.
  • تجنب التكرارات: إذا وجدت أن SQL الخاصة بك تنتج أخطاء، تحقق مرة أخرى من وجود تعريفات مكررة أو مشاكل في بناء الجملة.

من خلال اتباع هذه الإرشادات، يمكنك إنشاء جدولك بشكل فعال مع مفاتيح خارجية متعددة وتفادي الفخاخ الشائعة المرتبطة بقيود المفاتيح الخارجية. حظًا سعيدًا في مساعيك في MySQL ورمجة سعيدة!