एक घंटे के बाद, मैंने पाया कि इन शर्तों को १५० त्रुटि नहीं मिलने पर संतुष्ट होना चाहिए:
इससे पहले कि आप इसे संदर्भित करने के लिए एक विदेशी कुंजी परिभाषित करें, पैरेंट टेबल मौजूद होना चाहिए। आपको टेबल को सही क्रम में परिभाषित करना होगा: पैरेंट टेबल पहले, फिर चाइल्ड टेबल। यदि दोनों तालिकाएं एक दूसरे का संदर्भ देती हैं, तो आपको FK बाधाओं के बिना एक तालिका बनाना होगा, फिर दूसरी तालिका बनाएं, फिर FK बाधा को पहले तालिका में जोड़ें ALTER TABLE
।
दोनों तालिकाओं को विदेशी कुंजी बाधाओं का समर्थन करना चाहिए, अर्थात ENGINE=InnoDB
। अन्य भंडारण इंजन चुपचाप विदेशी कुंजी परिभाषाओं को अनदेखा करते हैं, इसलिए वे कोई त्रुटि या चेतावनी नहीं देते हैं, लेकिन एफके बाधा नहीं बचती है।
पैरेंट टेबल में संदर्भित कॉलम एक कुंजी के बाएं-सबसे कॉलम होना चाहिए। सबसे अच्छा अगर मूल में कुंजी है PRIMARY KEY
या UNIQUE KEY
।
FK परिभाषा को PK स्तंभ के समान क्रम में PK स्तंभ (संदर्भों) का संदर्भ देना चाहिए। उदाहरण के लिए, यदि FK REFERENCES Parent(a,b,c)
तो पेरेंट का PK क्रम में कॉलम पर परिभाषित नहीं होना चाहिए (a,c,b)
।
पैरेंट टेबल में PK कॉलम (s) चाइल्ड टेबल में FK कॉलम (s) के समान डेटा टाइप होना चाहिए। उदाहरण के लिए, यदि मूल तालिका में PK स्तंभ है UNSIGNED
, UNSIGNED
तो चाइल्ड टेबल फ़ील्ड में संबंधित कॉलम के लिए परिभाषित करना सुनिश्चित करें ।
अपवाद: तारों की लंबाई अलग हो सकती है। उदाहरण के लिए, VARCHAR(10)
संदर्भ VARCHAR(20)
या इसके विपरीत कर सकते हैं।
किसी भी स्ट्रिंग-प्रकार FK कॉलम (s) में समान PK सेट (s) के समान वर्ण सेट और कॉलेशन होना चाहिए।
यदि बाल तालिका में पहले से ही डेटा है, तो FK कॉलम (s) में प्रत्येक मान पैरेंट टेबल PK कॉलम (s) में एक मान से मेल खाना चाहिए। इसे क्वेरी की तरह देखें:
SELECT COUNT(*) FROM Child LEFT OUTER JOIN Parent ON Child.FK = Parent.PK
WHERE Parent.PK IS NULL;
यह शून्य (0) बेजोड़ मान वापस करना चाहिए। जाहिर है, यह क्वेरी एक सामान्य उदाहरण है; आपको अपनी तालिका नामों और स्तंभ नामों को प्रतिस्थापित करना होगा।
न तो पैरेंट टेबल और न ही चाइल्ड टेबल एक TEMPORARY
टेबल हो सकती है ।
न तो पैरेंट टेबल और न ही चाइल्ड टेबल एक PARTITIONED
टेबल हो सकती है ।
यदि आप ON DELETE SET NULL
विकल्प के साथ एक FK घोषित करते हैं , तो FK कॉलम (s) अशक्त होना चाहिए।
यदि आप एक विदेशी कुंजी के लिए एक बाधा नाम की घोषणा करते हैं, तो बाधा नाम पूरे स्कीमा में अद्वितीय होना चाहिए, न केवल उस तालिका में जिसमें बाधा को परिभाषित किया गया है। दो तालिकाओं में एक ही नाम के साथ अपनी बाधा नहीं हो सकती है।
यदि कोई अन्य FK अन्य तालिकाओं में उसी फ़ील्ड पर इंगित करता है, जिसके लिए आप नया FK बनाने का प्रयास कर रहे हैं, और वे विकृत हैं (यानी अलग-अलग टकराव), तो उन्हें पहले संगत बनाने की आवश्यकता होगी। यह पिछले परिवर्तनों का परिणाम हो सकता है जहां SET FOREIGN_KEY_CHECKS = 0;
गलती से परिभाषित असंगत संबंध के साथ उपयोग किया गया था। इन समस्याओं की पहचान कैसे करें FK के निर्देशों के लिए नीचे @ andrewdotn का उत्तर देखें।