2008-11-21 11 views
40

मैं MySQL डॉक्स here को देख रहा हूँ और विदेशी कुंजी और बाधाओं के बीच के अंतर को हल करने की कोशिश कर रहा। मैंने सोचा था कि एक FK था की कोई समस्या है, लेकिन डॉक्स उनके बारे में बात करने के लिए की तरह वे अलग बातें कर रहे हैं लगता है।MySQL शब्दावली बनाम "विदेशी कुंजी" अंतर "की कमी"?

बनाते हुए एक FK (आंशिक रूप से) है के लिए वाक्य रचना ...

[CONSTRAINT [symbol]] FOREIGN KEY 
    [index_name] (index_col_name, ...) 
    REFERENCES tbl_name (index_col_name,...) 

तो "बाधा" खंड वैकल्पिक है। आप इसे क्यों शामिल करेंगे या इसमें शामिल नहीं करेंगे? यदि आप इसे छोड़ देते हैं तो MySQL एक विदेशी कुंजी बनाता है लेकिन बाधा नहीं है? या आप के लिए एक नाम FK से ज्यादा कुछ नहीं है और अधिक एक "बाधा" की तरह यह है, इसलिए यदि आप यह निर्दिष्ट नहीं करते हैं तो आप एक गुमनाम FK मिल सकता है?

किसी भी स्पष्टीकरण बहुत सराहना की जाएगी।

धन्यवाद,

एतान

उत्तर

55

हाँ, एक विदेशी कुंजी बाधा का एक प्रकार है।

  • PRIMARY KEY: हाँ तालिका के रूप में बाधा और स्तंभ बाधा MySQL की कमी के लिए असमान समर्थन हासिल है।
  • FOREIGN KEY: हाँ तालिका बाधा के रूप में है, लेकिन केवल InnoDB और BDB भंडारण इंजन के साथ; अन्यथा पार्स किया लेकिन अनदेखा किया।
  • CHECK: पार्स लेकिन सभी भंडारण इंजन में नजरअंदाज कर दिया।
  • UNIQUE: हाँ तालिका बाधा और स्तंभ बाधा के रूप में।
  • NOT NULL: हाँ के रूप में स्तंभ बाधा।
  • DEFERRABLE और अन्य बाधा गुण: कोई समर्थन नहीं।

CONSTRAINT खंड आप बाधा स्पष्ट रूप से नाम के लिए, या तो मेटाडाटा अधिक पठनीय बनाने के लिए या किसी नाम का उपयोग करने के लिए जब आप बाधा ड्रॉप करना चाहते हैं अनुमति देता है। SQL मानक की आवश्यकता है कि CONSTRAINT खंड वैकल्पिक है। यदि आप इसे छोड़ देते हैं, तो आरडीबीएमएस स्वचालित रूप से एक नाम बनाता है, और नाम कार्यान्वयन तक है।

1

के लिए MySQL लेकिन FK की कमी कर रहे हैं का जवाब नहीं कर सकते। कुछ भी जो आपके डेटा को एक निश्चित स्थिति में मजबूर करता है वह एक बाधा है। बाधाओं के कई प्रकार होते हैं, अद्वितीय, प्राथमिक कुंजी, चेक करें और विदेशी कुंजी सभी बाधाओं रहे हैं। शायद MySQL दूसरों के पास है।

कभी-कभी शब्द आदेशों में अनुमति दी जाती है लेकिन DELETE कथन में से तरह पठनीयता के लिए sheerly की आवश्यकता नहीं।

9

सामान्य में (आवश्यक नहीं MySQL), विदेशी कुंजी की कमी है, लेकिन कमी हमेशा विदेशी कुंजी नहीं हैं। प्राथमिक कुंजी की कमी, अद्वितीय की कमी आदि

विशिष्ट प्रश्न के लिए वापस आ रहा है के बारे में सोचो, आप सही हैं, बाधा [प्रतीक] भाग को छोड़ते हुए एक स्वत: जनरेट नाम के साथ एक FK पैदा करेगा।

0

यह शायद MySQL में सबसे भ्रामक विषय है।

कई लोगों का कहना है कि, उदाहरण के लिए, 'प्राथमिक कुंजी', 'विदेशी कुंजी', और 'अद्वितीय' कुंजी वास्तव में अनुक्रमित रहे हैं!(MySQL आधिकारिक दस्तावेज यहां शामिल है)

दूसरी तरफ, कई अन्य लोग कहते हैं कि वे बाधाएं हैं (जो समझ में आता है, जब आप उनका उपयोग करते हैं, तो आप वास्तव में प्रभावित कॉलम पर प्रतिबंध लगा रहे हैं) ।

यदि वे वास्तव में इंडेक्स हैं, तो इसे नाम देने के लिए बाधा क्लॉजूल का उपयोग करने में क्या बात है, क्योंकि जब आप इसे बनाते हैं तो उस इंडेक्स के नाम का उपयोग करने में सक्षम होना चाहिए?

उदाहरण:

... विदेशी कुँजी INDEX_NAME (col_name1, col_name2, ...)

विदेशी कुंजी एक सूचकांक है, तो हम इसे संभाल करने INDEX_NAME उपयोग करने के लिए सक्षम होना चाहिए। हालांकि, हम नहीं कर सकते।

लेकिन अगर वे इंडेक्स नहीं हैं लेकिन वास्तविक बाधाएं जो काम करने के लिए इंडेक्स का उपयोग करती हैं, तो यह समझ में आता है।

किसी भी मामले में, हम नहीं जानते हैं। असल में, कोई भी नहीं जानता है।

1

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

1

अभी तक, हमारे निर्माण तालिका डीडीएल इस प्रारूप के हैं - अनन्य कुंजी और विदेशी कुंजी परिभाषा वाक्यविन्यास का उपयोग करें जो हमने उपयोग किया है।

CREATE TABLE my_dbschema.my_table (
    id INT unsigned auto_increment PRIMARY KEY, 
    account_nbr INT NOT NULL, 
    account_name VARCHAR(50) NOT NULL, 
    active_flg CHAR(1) NOT NULL DEFAULT 'Y', 
    vendor_nbr INT NOT NULL, 
    create_ts TIMESTAMP NOT NULL DEFAULT current_timestamp, 
    create_usr_id VARCHAR(10) NOT NULL DEFAULT 'DFLTUSR', 
    last_upd_ts TIMESTAMP NOT NULL DEFAULT current_timestamp ON UPDATE current_timestamp, 
    last_upd_usr_id VARCHAR(10) NOT NULL DEFAULT 'DFLTUSR', 
    UNIQUE KEY uk1_my_table(account_nbr, account_name), 
    FOREIGN KEY fk1_my_table(vendor_nbr) REFERENCES vendor(vendor_nbr) 
    ); 

इस प्रारूप में, MySQL सूचकांक-एस के नाम uk1_my_table और fk1_my_table स्वचालित रूप से पैदा कर रही है; लेकिन एफके ऑब्जेक्ट नाम कुछ अलग है - my_table_ibfk_1 (यानी tablename_ibfk_N - सिस्टम परिभाषित)। तो ALTER TABLE my_table DROP FOREIGN KEY fk1_my_table काम नहीं करेगा (और इसलिए अलार्म निराशाजनक और बढ़ाना), क्योंकि उस नाम से कोई एफके डीबी ऑब्जेक्ट नहीं है।

यहाँ एक वैकल्पिक DDL प्रारूप wrt constarints (: https://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html रेफरी): है -

CREATE TABLE my_dbschema.my_table (
    id INT unsigned auto_increment PRIMARY KEY, 
    account_nbr INT NOT NULL, 
    account_name VARCHAR(50) NOT NULL, 
    active_flg CHAR(1) NOT NULL DEFAULT 'Y', 
    vendor_nbr INT NOT NULL, 
    create_ts TIMESTAMP NOT NULL DEFAULT current_timestamp, 
    create_usr_id VARCHAR(10) NOT NULL DEFAULT 'DFLTUSR', 
    last_upd_ts TIMESTAMP NOT NULL DEFAULT current_timestamp ON UPDATE current_timestamp, 
    last_upd_usr_id VARCHAR(10) NOT NULL DEFAULT 'DFLTUSR', 
    CONSTRAINT uk1_my_table UNIQUE KEY (account_nbr, account_name), 
    CONSTRAINT fk1_my_table FOREIGN KEY (vendor_nbr) REFERENCES vendor(vendor_nbr) 
    ); 

इस प्रारूप में, MySQL अभी भी सूचकांक-एस के साथ नाम uk1_my_table और fk1_my_table स्वचालित रूप से पैदा कर रही है, लेकिन FK ऑब्जेक्ट नाम कुछ अलग नहीं है - यह डीडीएल में उल्लिखित fk1_my_table है। तो ALTER TABLE my_table DROP FOREIGN KEY fk1_my_table काम करता है, लेकिन नाम INDEX के पीछे छोड़ देता है।

और ध्यान दें कि ALTER TABLE my_table DROP INDEX fk1_my_table प्रारंभ में काम नहीं करेगा (जब एफके अभी तक नहीं छोड़ा गया है), एक त्रुटि संदेश के साथ कि इसका उपयोग एफके में किया जा रहा है! यदि डीआरओपी एफके कमांड सफलतापूर्वक निष्पादित किया गया है, तो केवल डीआरओपी इंडेक्स काम करता है।

आशा है कि यह बताता है और भ्रम को हल करने में मदद करता है।

+0

एक अच्छा जवाब! – HPM

संबंधित मुद्दे