سؤال

أقوم بعمل قاعدة بيانات صغيرة مع طاولة عمل MySQL. لدي جدول رئيسي ، يسمى "Immobili" ، والذي يحتوي على مفتاح أساسي يتكون من أربعة أعمدة: (Comune ، Via ، Civico ، Immobile).

الآن ، لديّ أيضًا ثلاثة طاولات أخرى ، ولدي نفس المفتاح الأساسي (Comune ، Via ، Civico ، mimobile) ، ولكن يتم الإشارة إلى هذه الحقول أيضًا إلى Immobili الجدول.

السؤال الأول: هل يمكنني عمل مفتاح أساسي هو أيضًا مفتاح خارجي؟

السؤال الثاني: عندما أحاول تصدير التغييرات التي يقولها: تنفيذ البرنامج النصي SQL في الخادم

# ERROR: Error 1005: Can't create table 'dbimmobili.condoni' (errno: 150)

CREATE  TABLE IF NOT EXISTS `dbimmobili`.`Condoni` (

  `ComuneImmobile` VARCHAR(50) NOT NULL ,
  `ViaImmobile` VARCHAR(50) NOT NULL ,
  `CivicoImmobile` VARCHAR(5) NOT NULL ,
  `InternoImmobile` VARCHAR(3) NOT NULL ,
  `ProtocolloNumero` VARCHAR(15) NULL ,
  `DataRichiestaSanatoria` DATE NULL ,
  `DataSanatoria` DATE NULL ,
  `SullePartiEsclusive` TINYINT(1) NULL ,
  `SullePartiComuni` TINYINT(1) NULL ,
  `OblazioneInEuro` DOUBLE NULL ,
  `TecnicoOblazione` VARCHAR(45) NULL ,
  `TelefonoTecnico` VARCHAR(15) NULL ,
  INDEX `ComuneImmobile` (`ComuneImmobile` ASC) ,
  INDEX `ViaImmobile` (`ViaImmobile` ASC) ,
  INDEX `CivicoImmobile` (`CivicoImmobile` ASC) ,
  INDEX `InternoImmobile` (`InternoImmobile` ASC) ,

  PRIMARY KEY (`ComuneImmobile`, `ViaImmobile`, `CivicoImmobile`, `InternoImmobile`) ,

  CONSTRAINT `ComuneImmobile`
    FOREIGN KEY (`ComuneImmobile` )
    REFERENCES `dbimmobili`.`Immobile` (`ComuneImmobile` )
    ON DELETE CASCADE
    ON UPDATE CASCADE,

  CONSTRAINT `ViaImmobile`
    FOREIGN KEY (`ViaImmobile` )
    REFERENCES `dbimmobili`.`Immobile` (`ViaImmobile` )
    ON DELETE CASCADE
    ON UPDATE CASCADE,

  CONSTRAINT `CivicoImmobile`
    FOREIGN KEY (`CivicoImmobile` )
    REFERENCES `dbimmobili`.`Immobile` (`CivicoImmobile` )
    ON DELETE CASCADE
    ON UPDATE CASCADE,

  CONSTRAINT `InternoImmobile`
    FOREIGN KEY (`InternoImmobile` )
    REFERENCES `dbimmobili`.`Immobile` (`InternoImmobile` )
    ON DELETE CASCADE
    ON UPDATE CASCADE
) ENGINE = InnoDB

إظهار حالة المحرك:

خطأ في القيد المفتاح الخارجي للجدول dbimmobili/valutazionimercato:

لا يمكن العثور على فهرس في الجدول المشار إليه حيث تظهر الأعمدة المشار إليها كأعمدة أولى ، أو أن الأعمدة تكتب في الجدول ولا يتطابق الجدول المشار إليه مع القيد. لاحظ أن نوع التخزين الداخلي من التعداد والتعيين الذي تم تغييره في الجداول التي تم إنشاؤها مع> = innodb-4.1.12 ، ولا يمكن الرجوع إلى هذه الأعمدة في الجداول القديمة بواسطة هذه الأعمدة في جداول جديدة.

أين أفعل خطأ؟

هل كانت مفيدة؟

المحلول

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

حالة اختبار:

CREATE TABLE tbl_a (
    id int PRIMARY KEY,
    some_other_id int,
    value int
) ENGINE=INNODB;
Query OK, 0 rows affected (0.10 sec)

CREATE TABLE tbl_b (
    id int PRIMARY KEY,
    a_id int,
    FOREIGN KEY (a_id) REFERENCES tbl_a (some_other_id)
) ENGINE=INNODB;
ERROR 1005 (HY000): Can't create table 'e.tbl_b' (errno: 150)

ولكن إذا أضفنا فهرسًا some_other_id:

CREATE INDEX ix_some_id ON tbl_a (some_other_id);
Query OK, 0 rows affected (0.11 sec)
Records: 0  Duplicates: 0  Warnings: 0

CREATE TABLE tbl_b (
    id int PRIMARY KEY,
    a_id int,
    FOREIGN KEY (a_id) REFERENCES tbl_a (some_other_id)
) ENGINE=INNODB;
Query OK, 0 rows affected (0.06 sec)

غالبًا ما لا تكون هذه مشكلة في معظم المواقف ، لأن الحقل المشار إليه غالبًا ما يكون المفتاح الأساسي للجدول المشار إليه ، ويتم فهرسة المفتاح الأساسي تلقائيًا.

نصائح أخرى

تحقق مزدوجًا من أن المفاتيح الأجنبية لها نفس النوع تمامًا مثل الحقل الذي حصلت عليه في هذا الجدول. على سبيل المثال ، يجب أن يكون كلاهما عدد صحيح (10) ، أو Varchar (8) ، حتى عدد الأحرف.

أدرك أن هذا منشور قديم ، لكنه يحتل المرتبة العالية في Google ، لذلك أقوم بإضافة ما اكتشفته لمشكلتي. إذا كان لديك مزيج من أنواع الجدول (مثل Myisam و Innodb) ، فستحصل على هذا الخطأ أيضًا. في هذه الحالة ، يكون Innodb هو نوع الجدول الافتراضي ، ولكن هناك حاجة إلى البحث عن النص الكامل بحيث تم ترحيله إلى Myisam. في هذه الحالة ، لا يمكنك إنشاء مفتاح خارجي في جدول InnoDB الذي يشير إلى جدول Myisam.

إذا كان المفتاح الخاص بك عبارة عن char/varchar أو شيء من هذا النوع ، فإن مشكلة أخرى محتملة هي ترتيب مختلف. تحقق مما إذا كان charset هو نفسه.

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

كانت متغيرات كلا العمود اللذين أردت ربطها هي أعداد صحيحة ، لكن واحدة من INTs قد تم فحصها "غير موقعة". ببساطة قم بتسجيل الخروج من خطأي.

كنت أحصل على خطأ نفس. لقد اكتشفت الحل الذي قمت بإنشائها المفتاح الأساسي في الجدول الرئيسي على أنه Bigint غير موقّع وأعلن أنه مفتاح خارجي في الجدول الثاني باعتباره Bigint فقط.

عندما أعلنت مفتاحي الخارجي باعتباره Bigint غير مهتم في الجدول الثاني ، كان كل شيء على ما يرام ، حتى أنه لم يكن بحاجة إلى إنشاء أي فهارس.

لذلك كان عدم تطابق نوع البيانات بين المفتاح الأساسي والمفتاح الأجنبي :)

كان لدي نفس المشكلة بالضبط ، لكن الحل لمشكلتي كان مختلفًا تمامًا. كان لدي ، في مكان آخر في قاعدة البيانات ، مفتاحًا خارجيًا بنفس الاسم. الذي تسبب في الخطأ 1005.

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

  1. تأكد من أن كلا الجدولين يستخدمون نفس نوع المحرك.
  2. تأكد من أن الحقول التي تقوم بها فهرسة لها نفس النوع والطول.

في حالتي ، كان الخطأ بسبب referencing الجدول MyISAM بينما referring كان الجدول InnoDB.

Converted محرك الجدول من MyISAM to InnoDB يحل المشكلة بالنسبة لي.

ALTER TABLE table_name ENGINE=InnoDB;

ليس لدي سمعة حتى الآن لأصوت اقتراح ستيف ، لكنه حل مشكلتي.

في حالتي ، تلقيت هذا الخطأ لأن الجدولين حيث تم إنشاؤهما باستخدام محركات قاعدة بيانات مختلفة-كان أحدهما innodb والآخر myisam.

يمكنك تغيير نوع قاعدة البيانات باستخدام: ALTER TABLE T ENGUER = MYISAM ؛

@نرى http://dev.mysql.com/doc/refman/5.1/en/storage-egine-setting.html

انتبه الى charset و تجميع المعلمات عند إنشاء جدول. من حيث المفتاح الخارجي مشاكل شيء من هذا القبيل:

CREATE TABLE yourTableName (
....
....
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

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

Error Code: 1253. COLLATION 'utf8_unicode_ci' is not valid for CHARACTER SET 'latin1'

بعد هذا التصحيح تم حل مشكلتي.

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

إذا كان لدى أي شخص هذا الخطأ مع علاقات FK/PK التي يبدو جيدًا على ما يبدو واستخدمت الأداة المرئية ، فحاول حذف أعمدة FK المخالفة وإعادة تضافتها في الأداة. كنت أحصل باستمرار على هذا الخطأ حتى أعيد صياغة الاتصالات التي قمت بمسح المشكلات.

عندما يكون هناك عمودين للمفاتيح الأولية ، فإنها تشكل مفتاحًا أساسيًا مركبًا ، وبالتالي عليك التأكد من أنه في الجدول الذي يتم الرجوع إليه ، يوجد أيضًا عمودين من نفس نوع البيانات.

بالنسبة لي ، كنت أحاول مطابقة حقل فهرسة منتظم في طاولة طفل ، إلى مفتاح أساسي في الجدول الأصل ، وعلى افتراضي بعض واجهة المستخدم الرسومية MySQL مثل Sequel Pro تعيين المفتاح الأساسي على أنه غير موقّع ، لذلك عليك التأكد أن حقل طاولة الطفل غير موقّع أيضًا (ما لم تكن هذه الحقول تحتوي على ints سلبية ، ثم تأكد من توقيع كلاهما).

MySQL غريب الأطوار ، خاصة فيما يتعلق بالمفاتيح والمشغلات الأجنبية. أنا الآن في عملية توصيل قاعدة بيانات واحدة من هذا القبيل ، وواجهت هذه المشكلة. إنه ليس واضحًا أو بديهيًا ، لذلك يذهب هنا:

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

تتمثل الممارسة الجيدة في تنظيف الجداول المشاركة في العلاقات للتأكد من أن المحاولات السابقة لم تنشئ فهارس لا تريدها أو تحتاجها.

آمل أن يكون ذلك قد ساعد ، بعض أخطاء MySQL مجنونة في التتبع.

السؤال الأول: هل يمكنني عمل مفتاح أساسي هو أيضًا مفتاح خارجي؟

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

# خطأ: خطأ 1005: لا يمكن إنشاء جدول "dbimmobili.condoni" (Errno: 150)

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

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

1. اجعل جميع المفاتيح الأجنبية الأولية في جدول البحث (1 في 1 إلى العديد).

في حالتي ، تضمن هذا الأمر تغيير المعرف باعتباره PK إلى اسم المستخدم في TBL_USERS ، إلى اسم المستخدم والشركة في TBL_COMPANIES ، وإلى اسم المستخدم والشركة والاتصال في TBL_COMPANY_CONTACTS. إنه تطبيق لعدة مستخدمين لإدخال جهات اتصال متعددة للشركة ، مما يسمح بالتداخل والاختباء لجهات اتصال المستخدمين الآخرين.

2. احذف جميع علاقات الرسم البياني وجميع فهرس الجدول التي ليست مفاتيح أساسية.

هذا يعمل على إصلاح معظم مشكلات الفهرس التي تسببها حقًا منضدة عمل عربات التي تجرها الدواب MySQL.

3. إذا قمت بذلك من البداية إلى النهاية ، فقم بإسقاط المخطط على الخادم حتى لا يتم الخلط بين طاولة عمل MySQL بشأن الفهرس الحالي وتفتقر إلى هناك في النموذج (المشكلة تسببت في مؤشر BBY وعلاقة المفتاح الأجنبي ، وليس الفهرس وحده ).

هذا يقلل من الكثير من القرارات التي يتعين على DB و Server و MySQL Workbench اتخاذ الكثير. هذه القرارات حول كيفية إعادة توجيه المهندس شيء معقد وذكي ، ولكنه غير كامل.

4. الآن ، أنا أعتبر هذا العودة إلى المربع الأول (بشكل عام بعد التصميم بسرعة كبيرة دون عملية تخطو). لا يزال لدي جميع الطاولات ، لكنها نظيفة في هذه المرحلة. الآن أنت فقط:

أولاً ، المهندس الأمامي فقط للتأكد من أن الجداول (بدون علاقات) تعمل كما هو متوقع.

اتبع سلسلة العلاقة لأسفل من خلال المفاتيح الأساسية ، بدءًا من الجزء العلوي من الجدول (أنا حالتي TBL_USERS إلى TBL_COMPANIES). بعد كل علاقة ، دائمًا مهندس إلى التأكد من ذلك أشواط, ، ثم احفظ النموذج وأغلق ، ثم عكس الطراز للتأكد من ذلك يأخذ. يتيح لك ذلك عزل المشكلات بسرعة عند ظهورها ، في حالتي المتبقية على الفهرس المستخدمة من قبل المفاتيح الأجنبية القديمة المحذوفة (حدث 2-3 مرات).

و Tadda ، مرة أخرى حيث كنت بحاجة إلى أن تكون.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top