MySQL गलत बनाने वाली विदेशी कुंजी के साथ तालिकाओं का निर्माण: 150


98

मैं दो विदेशी कुंजियों के साथ MySQL में एक तालिका बनाने की कोशिश कर रहा हूं, जो 2 अन्य तालिकाओं में प्राथमिक कुंजियों का संदर्भ देती है, लेकिन मुझे एक त्रुटि मिल रही है: 150 त्रुटि और यह तालिका नहीं बनाएगी।

यहाँ सभी 3 तालिकाओं के लिए SQL है:

CREATE TABLE role_groups (
  `role_group_id` int(11) NOT NULL `AUTO_INCREMENT`,
  `name` varchar(20),
  `description` varchar(200),
  PRIMARY KEY (`role_group_id`)
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS `roles` (
  `role_id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50),
  `description` varchar(200),
  PRIMARY KEY (`role_id`)
) ENGINE=InnoDB;

create table role_map (
  `role_map_id` int not null `auto_increment`,
  `role_id` int not null,
  `role_group_id` int not null,
  primary key(`role_map_id`),
  foreign key(`role_id`) references roles(`role_id`),
  foreign key(`role_group_id`) references role_groups(`role_group_id`)
) engine=InnoDB;

किसी भी तरह की सहायता का स्वागत किया जाएगा।


1
क्या आप त्रुटि आउटपुट पोस्ट कर सकते हैं और हमें बता सकते हैं कि कौन सी कमांड (तीन में से) त्रुटि पैदा कर रही है?
डेव

4
बैक-टिक्स के साथ क्या होता है auto_increment? यह मान्य नहीं है। Auto_increment एक कीवर्ड है, न कि कोई पहचानकर्ता।
बिल कार्वेन

जवाबों:


238

मुझे भी यही समस्या थी ALTER TABLE ADD FOREIGN KEY

एक घंटे के बाद, मैंने पाया कि इन शर्तों को १५० त्रुटि नहीं मिलने पर संतुष्ट होना चाहिए:

  1. इससे पहले कि आप इसे संदर्भित करने के लिए एक विदेशी कुंजी परिभाषित करें, पैरेंट टेबल मौजूद होना चाहिए। आपको टेबल को सही क्रम में परिभाषित करना होगा: पैरेंट टेबल पहले, फिर चाइल्ड टेबल। यदि दोनों तालिकाएं एक दूसरे का संदर्भ देती हैं, तो आपको FK बाधाओं के बिना एक तालिका बनाना होगा, फिर दूसरी तालिका बनाएं, फिर FK बाधा को पहले तालिका में जोड़ें ALTER TABLE

  2. दोनों तालिकाओं को विदेशी कुंजी बाधाओं का समर्थन करना चाहिए, अर्थात ENGINE=InnoDB। अन्य भंडारण इंजन चुपचाप विदेशी कुंजी परिभाषाओं को अनदेखा करते हैं, इसलिए वे कोई त्रुटि या चेतावनी नहीं देते हैं, लेकिन एफके बाधा नहीं बचती है।

  3. पैरेंट टेबल में संदर्भित कॉलम एक कुंजी के बाएं-सबसे कॉलम होना चाहिए। सबसे अच्छा अगर मूल में कुंजी है PRIMARY KEYया UNIQUE KEY

  4. FK परिभाषा को PK स्तंभ के समान क्रम में PK स्तंभ (संदर्भों) का संदर्भ देना चाहिए। उदाहरण के लिए, यदि FK REFERENCES Parent(a,b,c)तो पेरेंट का PK क्रम में कॉलम पर परिभाषित नहीं होना चाहिए (a,c,b)

  5. पैरेंट टेबल में PK कॉलम (s) चाइल्ड टेबल में FK कॉलम (s) के समान डेटा टाइप होना चाहिए। उदाहरण के लिए, यदि मूल तालिका में PK स्तंभ है UNSIGNED, UNSIGNEDतो चाइल्ड टेबल फ़ील्ड में संबंधित कॉलम के लिए परिभाषित करना सुनिश्चित करें ।

    अपवाद: तारों की लंबाई अलग हो सकती है। उदाहरण के लिए, VARCHAR(10)संदर्भ VARCHAR(20)या इसके विपरीत कर सकते हैं।

  6. किसी भी स्ट्रिंग-प्रकार FK कॉलम (s) में समान PK सेट (s) के समान वर्ण सेट और कॉलेशन होना चाहिए।

  7. यदि बाल तालिका में पहले से ही डेटा है, तो FK कॉलम (s) में प्रत्येक मान पैरेंट टेबल PK कॉलम (s) में एक मान से मेल खाना चाहिए। इसे क्वेरी की तरह देखें:

    SELECT COUNT(*) FROM Child LEFT OUTER JOIN Parent ON Child.FK = Parent.PK 
    WHERE Parent.PK IS NULL;

    यह शून्य (0) बेजोड़ मान वापस करना चाहिए। जाहिर है, यह क्वेरी एक सामान्य उदाहरण है; आपको अपनी तालिका नामों और स्तंभ नामों को प्रतिस्थापित करना होगा।

  8. न तो पैरेंट टेबल और न ही चाइल्ड टेबल एक TEMPORARYटेबल हो सकती है ।

  9. न तो पैरेंट टेबल और न ही चाइल्ड टेबल एक PARTITIONEDटेबल हो सकती है ।

  10. यदि आप ON DELETE SET NULLविकल्प के साथ एक FK घोषित करते हैं , तो FK कॉलम (s) अशक्त होना चाहिए।

  11. यदि आप एक विदेशी कुंजी के लिए एक बाधा नाम की घोषणा करते हैं, तो बाधा नाम पूरे स्कीमा में अद्वितीय होना चाहिए, न केवल उस तालिका में जिसमें बाधा को परिभाषित किया गया है। दो तालिकाओं में एक ही नाम के साथ अपनी बाधा नहीं हो सकती है।

  12. यदि कोई अन्य FK अन्य तालिकाओं में उसी फ़ील्ड पर इंगित करता है, जिसके लिए आप नया FK बनाने का प्रयास कर रहे हैं, और वे विकृत हैं (यानी अलग-अलग टकराव), तो उन्हें पहले संगत बनाने की आवश्यकता होगी। यह पिछले परिवर्तनों का परिणाम हो सकता है जहां SET FOREIGN_KEY_CHECKS = 0;गलती से परिभाषित असंगत संबंध के साथ उपयोग किया गया था। इन समस्याओं की पहचान कैसे करें FK के निर्देशों के लिए नीचे @ andrewdotn का उत्तर देखें।

उम्मीद है की यह मदद करेगा।


4
जोड़ने लायक एक और बात: यदि मूल तालिका का PK एक से अधिक फ़ील्ड है, तो FK में फ़ील्ड का क्रम PK में समान होना चाहिए
Kip

26
इसमें int(11) unsigned NOT NULLबनाम जैसी चीजें शामिल हैं int(11) NOT NULL
ग्लेन सोलबेरी

4
वैकल्पिक टेबल table_name इंजन = InnoDB;
तोलमेरा

12
यदि तालिका को परिभाषित किया गया है तो इंजन = MyISAM यह गलत 150 उत्पन्न नहीं करता है क्योंकि यह विदेशी प्रमुख घोषणाओं की अनदेखी करता है । यह अपने ऑटोमोबाइल इंजन के साथ परेशानी से बचने का सबसे अच्छा तरीका है जैसे कि नाव चलाना। :-)
बिल कार्विन

2
इसके अलावा, अगर आपके CONSTRAINT का ON DELETEनियम SET NULLसुनिश्चित करता है कि विदेशी कुंजी वास्तव में NULL हो सकती है! मैंने इस जवाब को बार-बार पढ़ते हुए 30 मिनट बिताए, यह सुनिश्चित करते हुए कि मेरी टेबल शर्तों को पूरा करती हैं, लेकिन फिर भी त्रुटि 150 हो रही है। तब मैंने देखा कि मेरा FK एक नॉट नाल फील्ड नहीं था जिसका अर्थ है कि नियम लागू करना असंभव था।
मार्टिन जॉइनर

62

MySQL के सामान्य "गलत 150" संदेश का मतलब है कि एक विदेशी कुंजी बाधा सही ढंग से नहीं बनी थी । " जैसा कि आप शायद पहले से ही जानते हैं कि अगर आप इस पृष्ठ को पढ़ रहे हैं, तो सामान्य "ग़लती: 150" त्रुटि संदेश वास्तव में अनपेक्षित है। तथापि:

आप वास्तविक त्रुटि संदेश चलाकर SHOW ENGINE INNODB STATUS;और फिर LATEST FOREIGN KEY ERRORआउटपुट में खोज सकते हैं।

उदाहरण के लिए, एक विदेशी कुंजी बाधा बनाने का यह प्रयास:

CREATE TABLE t1
(id INTEGER);

CREATE TABLE t2
(t1_id INTEGER,
 CONSTRAINT FOREIGN KEY (t1_id) REFERENCES t1 (id));

त्रुटि के साथ विफल रहता है Can't create table 'test.t2' (errno: 150)। यह किसी के लिए उपयोगी के अलावा कुछ नहीं बताता है कि यह एक विदेशी महत्वपूर्ण समस्या है। लेकिन भागो SHOW ENGINE INNODB STATUS;और यह कहेगा:

------------------------
LATEST FOREIGN KEY ERROR
------------------------
130811 23:36:38 Error in foreign key constraint of table test/t2:
FOREIGN KEY (t1_id) REFERENCES t1 (id)):
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.

यह कहता है कि समस्या यह है कि इसे एक सूचकांक नहीं मिल सकता है। SHOW INDEX FROM t1यह दर्शाता है कि तालिका के लिए कोई अनुक्रमणिका नहीं है t1। तय करें कि, प्राथमिक कुंजी को परिभाषित करके t1, और विदेशी कुंजी बाधा सफलतापूर्वक बनाई जाएगी।


4
SHOW ENGINE INNODB STATUSलगभग एक घंटे के लिए निदान करने की कोशिश कर रहे एक समस्या की पहचान करने में मैंने तुरंत मदद की। धन्यवाद।
जेट्रीम

मेरे मामले में, यह इंगित करता है कि एक पूरी तरह से अलग तालिका है कि FK'd एक ही क्षेत्र मैं इंगित करने के लिए असंगत था और इसलिए नए एक को बचाने नहीं होगा ... यह मानते हुए कि यह SET FOREIGN_KEY_CHECKS = 0;आयात / परिवर्तन के दौरान उपयोग करने से था जो विकृत था एक समय में या किसी अन्य पर। बड़ी मदद, धन्यवाद।
बाउल

25

सुनिश्चित करें कि आप जिन दो क्षेत्रों को एक बाधा से जोड़ने का प्रयास कर रहे हैं, उनके गुण बिल्कुल समान हैं।

अक्सर, एक आईडी कॉलम पर 'अहस्ताक्षरित' संपत्ति आपको पकड़ लेगी।

ALTER TABLE `dbname`.`tablename` CHANGE `fieldname` `fieldname` int(10) UNSIGNED NULL;

मेरे अनुभव में, यह देखने के लिए कि आपके मुख्य सूचकांक कॉलम के खिलाफ क्या झंडे लगाए गए हैं, यह जाँचने के लिए MySQL के SHOW CREATE टेबल का उपयोग करने के लायक है, फिर उन्हें अपने विदेशी कुंजी कॉलम में कॉपी करें। वहाँ चीजें हो सकती हैं, जैसे "अहस्ताक्षरित" जो स्पष्ट नहीं हैं।
अंबुलारे

10

जब आप यह स्क्रिप्ट चलाते हैं तो आपके डेटाबेस की वर्तमान स्थिति क्या है? क्या यह पूरी तरह से खाली है? खरोंच से एक डेटाबेस बनाते समय आपकी एसक्यूएल मेरे लिए ठीक चलती है, लेकिन गलत 150 को आमतौर पर एक विदेशी कुंजी का हिस्सा होने वाली तालिकाओं को छोड़ने और फिर से बनाना होता है। मुझे लग रहा है कि आप 100% नए और नए डेटाबेस के साथ काम नहीं कर रहे हैं।

यदि आप अपनी SQL फ़ाइल को "स्रोत" करते समय गलत कर रहे हैं, तो आपको अधिक विस्तृत त्रुटि जानकारी देखने के लिए "स्रोत" कमांड के तुरंत बाद MySQL प्रॉम्प्ट से "SHOW इंजन INNODB STATUS" कमांड चलाने में सक्षम होना चाहिए।

आप मैन्युअल प्रविष्टि की भी जाँच कर सकते हैं:

यदि आप एक टेबल को फिर से बनाते हैं जो गिरा दिया गया था, तो इसकी एक परिभाषा होनी चाहिए जो इसे संदर्भित करने वाले विदेशी प्रमुख बाधाओं के अनुरूप हो। इसमें सही कॉलम नाम और प्रकार होने चाहिए, और इसमें संदर्भित कुंजियों पर अनुक्रमित होना चाहिए, जैसा कि पहले कहा गया है। यदि ये संतुष्ट नहीं होते हैं, तो MySQL त्रुटि संख्या 1005 देता है और त्रुटि संदेश में त्रुटि 150 को संदर्भित करता है। यदि MySQL एक क्रिएट टेबल स्टेटमेंट से 1005 नंबर की त्रुटि रिपोर्ट करता है, और त्रुटि संदेश 150 को संदर्भित करता है, तो टेबल निर्माण विफल हो गया क्योंकि एक विदेशी कुंजी बाधा सही रूप से नहीं बनाई गई थी।

- MySQL 5.1 संदर्भ मैनुअल


5

जो लोग इस धागे को उसी समस्या के साथ देख रहे हैं:

इस तरह की त्रुटियां होने के कई कारण हैं। माईएसक्यूएल में विदेशी प्रमुख त्रुटियों के कारणों और समाधानों की एक पूरी सूची के लिए (यहाँ उन पर चर्चा की गई है), इस लिंक को देखें:

MySQL फॉरेन की एरर और एर्रनो 150


4

अन्य लोगों के लिए जो Google के माध्यम से इस SO प्रविष्टि को ढूंढते हैं: सुनिश्चित करें कि आप किसी विदेशी कुंजी पर एक SET NULL क्रिया करने की कोशिश नहीं कर रहे हैं (स्तंभ होना) "NOT NULL।" जब तक मुझे एक CHECK इंजन INNODB STATUS करने की याद नहीं आई तब तक बहुत निराशा हुई।


3

निश्चित रूप से ऐसा नहीं है, लेकिन मुझे यह गलती बहुत सामान्य और अटपटी लगी। एक का लक्ष्य FOREIGN KEYनहीं हो सकता है PRIMARY KEY। ते उत्तर जो मेरे लिए उपयोगी हो गया है:

एक अग्रगण्य कुंजी हमेशा अन्य तालिका के एक प्राथमिक कुंजी सच्चे क्षेत्र की ओर इंगित की जानी चाहिए।

CREATE TABLE users(
   id INT AUTO_INCREMENT PRIMARY KEY,
   username VARCHAR(40));

CREATE TABLE userroles(
   id INT AUTO_INCREMENT PRIMARY KEY,
   user_id INT NOT NULL,
   FOREIGN KEY(user_id) REFERENCES users(id));

3

जैसा कि @andrewdotn द्वारा बताया गया है कि SHOW ENGINE INNODB STATUS;केवल एक त्रुटि कोड के बजाय विस्तृत त्रुटि ( ) को देखना सबसे अच्छा तरीका है ।

कारणों में से एक यह हो सकता है कि एक सूचकांक पहले से ही समान नाम के साथ मौजूद है, दूसरी तालिका में हो सकता है। एक अभ्यास के रूप में, मैं इस तरह के टकराव से बचने के लिए सूचकांक नाम से पहले तालिका का नाम उपसर्ग करने की सलाह देता हूं। idx_userIdउपयोग के बजाय उदा idx_userActionMapping_userId


3

कृपया पहले यह सुनिश्चित कर लें

  1. आप InnoDB तालिकाओं का उपयोग कर रहे हैं।
  2. FOREIGN KEY के लिए फ़ील्ड का स्रोत फ़ील्ड के समान प्रकार और लंबाई (!) है।

मुझे भी यही परेशानी थी और मैंने इसे ठीक कर लिया है। मैं एक क्षेत्र के लिए INT अहस्ताक्षरित था और अन्य क्षेत्र के लिए सिर्फ पूर्णांक।


2

सहायक टिप, SHOW WARNINGS;अपनी CREATEक्वेरी आज़माने के बाद उपयोग करें और आपको त्रुटि के साथ-साथ अधिक विस्तृत चेतावनी मिलेगी:

    ---------------------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                                                                                                                                                                 |
+---------+------+--------------------------------------------------------------------------                          --------------------------------------------------------------------------------------------                          ---------------+
| Warning |  150 | Create table 'fakeDatabase/exampleTable' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns.
|
| Error   | 1005 | Can't create table 'exampleTable' (errno:150)                                                                                                                                                                           |
+---------+------+--------------------------------------------------------------------------                          --------------------------------------------------------------------------------------------                          ---------------+

तो इस मामले में, मेरी तालिका को फिर से बनाने का समय!


1

यह आमतौर पर तब होता है जब आप मौजूदा डेटाबेस में स्रोत फ़ाइल की कोशिश करते हैं। पहले सभी तालिकाओं को गिराएं (या स्वयं DB)। और फिर SET foreign_key_checks = 0;शुरुआत और SET foreign_key_checks = 1;अंत में स्रोत फ़ाइल ।


1

मैंने एक और कारण पाया है कि यह विफल रहता है ... केस संवेदी तालिका नाम।

इस तालिका की परिभाषा के लिए

CREATE TABLE user (
  userId int PRIMARY KEY AUTO_INCREMENT,
  username varchar(30) NOT NULL
) ENGINE=InnoDB;

यह तालिका परिभाषा काम करती है

CREATE TABLE product (
  id int PRIMARY KEY AUTO_INCREMENT,
  userId int,
  FOREIGN KEY fkProductUser1(userId) REFERENCES **u**ser(userId)
) ENGINE=InnoDB;

जबकि यह विफल रहता है

CREATE TABLE product (
  id int PRIMARY KEY AUTO_INCREMENT,
  userId int,
  FOREIGN KEY fkProductUser1(userId) REFERENCES User(userId)
) ENGINE=InnoDB;

तथ्य यह है कि यह विंडोज पर काम करता था और यूनिक्स पर असफल होने में मुझे कुछ घंटे लग गए। आशा है कि किसी और की मदद करता है।


1

मैक ओएस के लिए MySQL कार्यक्षेत्र 6.3।

समस्या: एक एक्स डायग्राम पर फॉरवर्ड इंजीनियरिंग करने का प्रयास करने पर तालिका X पर गलत 150, 21 में से 20 सफल हुए, 1 असफल रहा। यदि तालिका X पर FK को हटा दिया गया था, तो त्रुटि एक अलग तालिका में चली गई जो पहले विफल नहीं हुई थी।

MyISAM में सभी टेबल इंजन को बदल दिया और यह ठीक काम किया।

यहां छवि विवरण दर्ज करें


0

यह भी जाँचने योग्य है कि आप गलती से गलत डेटाबेस पर काम नहीं कर रहे हैं। यह त्रुटि तब होगी जब विदेशी तालिका मौजूद नहीं है। MySQL को इतना गूढ़ क्यों होना पड़ता है?


0

सुनिश्चित करें कि विदेशी कुंजी को पैरेंट में अद्वितीय के रूप में सूचीबद्ध नहीं किया गया है। मुझे भी यही समस्या थी और मैंने इसे सीमांकित करते हुए इसे अद्वितीय नहीं बताया।


0

मेरे मामले में यह इस तथ्य के कारण था कि जो क्षेत्र एक विदेशी कुंजी क्षेत्र था, उसका बहुत लंबा नाम था। foreign key (some_other_table_with_long_name_id)। Sth कम करके देखें। उस स्थिति में त्रुटि संदेश थोड़ा भ्रामक है।

इसके अलावा, जैसा कि @Jon ने पहले उल्लेख किया है - क्षेत्र की परिभाषाएं समान होनी चाहिए ( unsignedउपप्रकार के लिए बाहर देखें )।


0

(टिप्पणी के लिए साइड नोट्स बहुत बड़े हैं)

इसके लिए कोई जरूरत नहीं है AUTO_INCREMENTमानचित्रण तालिका में आईडी ; से मुक्त होना।

बदले PRIMARY KEYके लिए(role_id, role_group_id) (या तो क्रम में)। इससे पहुंच और तेज होगी।

चूंकि आप शायद दोनों दिशाओं को मैप करना चाहते हैं, INDEXइसलिए विपरीत क्रम में उन दो कॉलमों के साथ भी जोड़ें । (इसे बनाने की कोई आवश्यकता नहीं हैUNIQUE ।)

अधिक सुझाव: http://mysql.rjweb.org/doc.php/index_cookbook_mysql#speeding_up_wp_postmeta



0

तालिका बनाने से पहले लाइन के नीचे निष्पादित करें: SET FOREIGN_KEY_CHECKS = 0;

FOREIGN_KEY_CHECKS विकल्प निर्दिष्ट करता है कि InnoDB तालिकाओं के लिए विदेशी कुंजी बाधाओं की जाँच करें या नहीं।

- विदेशी प्रमुख बाधाओं की जाँच करने के लिए निर्दिष्ट करें (यह डिफ़ॉल्ट है)

SET FOREIGN_KEY_CHECKS = 1;

 

- विदेशी प्रमुख बाधाओं की जांच न करें

SET FOREIGN_KEY_CHECKS = 0;

जब उपयोग करने के लिए: अस्थायी रूप से अक्षम करने योग्य संदर्भ बाधाएं (FOREIGN_KEY_CHECKS को 0 पर सेट करें) तब उपयोगी होती है जब आपको किसी भी अभिभावक-बच्चे के क्रम में तालिकाएँ और डेटा लोड करने की आवश्यकता होती है


-1

मुझे उसी समस्या का सामना करना पड़ा, लेकिन मुझे पता चलता है कि मेरे पास मूल तालिका नहीं थी। इसलिए मैं सिर्फ बच्चे के प्रवास के सामने माता-पिता के प्रवास को संपादित करता हूं। बस कर दो।


1
इस जवाब के बजाय एक टिप्पणी होनी चाहिए थी
हन्नाद रहमान
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.