क्या किसी विदेशी कुंजी के साथ टेबल कॉलम NULL हो सकते हैं?


235

मेरे पास एक टेबल है जिसमें अन्य तालिकाओं के लिए कई आईडी कॉलम हैं।

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

(यह संभावना डेटाबेस सर्वर पर निर्भर है, मैं MySQL और InnoDB तालिका प्रकार का उपयोग कर रहा हूं)

मेरा मानना ​​है कि यह एक उचित उम्मीद है, लेकिन अगर मैं गलत हूं तो मुझे सुधारें।


6
मैं MySQL के बारे में नहीं जानता, लेकिन एमएस एसक्यूएल सर्वर विदेशी कुंजियों को आप चाहते हैं कि शब्दार्थ के साथ अशक्त होने की अनुमति देता है। मुझे उम्मीद है कि मानक व्यवहार है।
जेफरी एल व्हाइटलेज

1
विदेशी कुंजी, mySQL में डिफ़ॉल्ट रूप से शून्य नहीं हो सकती है, इसका कारण सरल है, यदि आप कुछ संदर्भ देते हैं और आप इसे शून्य करते हैं, तो आप डेटा अखंडता को ढीला कर देंगे। जब आप तालिका सेट बनाते हैं तो शून्य को अनुमति नहीं देते हैं और फिर विदेशी कुंजी बाधा को लागू करते हैं। आप अपडेट पर शून्य सेट नहीं कर सकते, यह आपको एक त्रुटि भेजनी चाहिए, लेकिन आप (आप को) केवल इस कॉलम को अपडेट नहीं करना चाहिए और केवल उन फ़ील्ड्स को अपडेट करना चाहिए जिन्हें आपको बदलने की आवश्यकता है।
जोएलबॉनेट

जवाबों:


245

हां, आप बाधा तभी लागू कर सकते हैं जब मूल्य NULL नहीं है। इसे निम्न उदाहरण से आसानी से परखा जा सकता है:

CREATE DATABASE t;
USE t;

CREATE TABLE parent (id INT NOT NULL,
                     PRIMARY KEY (id)
) ENGINE=INNODB;

CREATE TABLE child (id INT NULL, 
                    parent_id INT NULL,
                    FOREIGN KEY (parent_id) REFERENCES parent(id)
) ENGINE=INNODB;


INSERT INTO child (id, parent_id) VALUES (1, NULL);
-- Query OK, 1 row affected (0.01 sec)


INSERT INTO child (id, parent_id) VALUES (2, 1);

-- ERROR 1452 (23000): Cannot add or update a child row: a foreign key 
-- constraint fails (`t/child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY
-- (`parent_id`) REFERENCES `parent` (`id`))

पहला इंसर्ट पास होगा क्योंकि हम एक NULL को इनसर्ट करते हैं parent_id। विदेशी कुंजी बाधा के कारण दूसरा इंसर्ट विफल हो जाता है, क्योंकि हमने parentटेबल में मौजूद मूल्य को सम्मिलित करने का प्रयास किया है ।


16
मूल तालिका को INT INT NOT NULL के साथ भी घोषित किया जा सकता है।
विल

@CJDennis यदि आप इसे बनाते हैं ताकि केवल एक पंक्ति में एक अशक्त आईडी हो, इसे अन्य पंक्तियों के लिए फ़ॉलबैक मान के रूप में उपयोग किया जा सकता है। (हालांकि यह डीबी के लिए बेहतर काम कर सकता है यदि आप बस अधिक कॉलम का उपयोग करते हैं।) डिफ़ॉल्ट बाधा एक समस्या की तरह लगती है यदि आप बाद में जानना चाहते हैं कि क्या मूल रूप से "डिफ़ॉल्ट" (शून्य का उपयोग करके) सेट किया गया था या एक सेट किया गया था मान जो "डिफ़ॉल्ट" के समान होता है। एक नल आईडी के साथ एक पंक्ति होने से, आप स्पष्ट रूप से संकेत दे सकते हैं कि इस पंक्ति को एक सामान्य पंक्ति के रूप में उपयोग नहीं किया जाना है, और अन्य पंक्तियों के लिए एक प्रकार का गतिशील डिफ़ॉल्ट मान प्रदान करने के तरीके के रूप में पंक्ति का उपयोग कर सकते हैं।
ओरूरबोरस

1
मुझे लगता है कि यह parent_id INT NULLहिस्सा ( parent_id int default null

जावा उपयोगकर्ताओं के लिए साइड नोट, यदि आप अपने वर्ग के सदस्यों के intबजाय ibatis या अन्य ORM और उपयोगकर्ता का उपयोग Integerकरते हैं तो डिफ़ॉल्ट कभी शून्य नहीं होगा, लेकिन 0 होगा और आप बाधा को विफल कर देंगे।
जिम फोर्ड

32

मैंने पाया कि डालते समय, नल स्तंभ मानों को विशेष रूप से NULL घोषित किया जाना था, अन्यथा मुझे एक बाधा उल्लंघन त्रुटि मिलेगी (जैसा कि एक रिक्त स्ट्रिंग के विपरीत)।


8
क्या आप इसे अनुमति देने के लिए कॉलम पर NULL का डिफ़ॉल्ट मान सेट नहीं कर सकते?
केविन कूलोमबे

हां, ज्यादातर भाषाओं में NULL एक खाली स्ट्रिंग से अलग है। शायद शुरू होने पर सूक्ष्म, लेकिन याद रखने के लिए महत्वपूर्ण है।
गैरी

अरे बैकस्लाइडर, आप कहते हैं "(एक खाली स्ट्रिंग के विपरीत)", लेकिन मुझे नहीं लगता है कि आपका मतलब यह है कि आप खाली स्ट्रिंग का मूल्य प्राप्त करेंगे, बल्कि यह मान लें कि आप मान के लिए एक मान निर्दिष्ट नहीं करते हैं सब? यानी आप अपने कॉलम में भी उल्लेख नहीं करते हैं INSERT INTO {table} {list_of_columns}? क्योंकि मेरे लिए यह सच है; स्तंभ के उल्लेख को छोड़ने से त्रुटि होती है, लेकिन इसमें शामिल हैं और स्पष्ट रूप से NULL को त्रुटि पर सेट करना है। अगर मैं सही हूं, तो मुझे लगता है कि @ गैरी की टिप्पणी लागू नहीं होती है (क्योंकि आपका मतलब खाली-स्ट्रिंग नहीं था), लेकिन @ क्वीन कूलॉमबे मददगार हो सकता है ...
द रेड मटर

हां, @ KevinCoulombe का सुझाव काम करता है, मैंने इसका वर्णन एंटिटी फ्रेमवर्क कोर के माइग्रेशन लिपियों के साथ किया, यहाँ देखें
द रेड मटर

यह इंगित करना महत्वपूर्ण है कि NULL विदेशी कुंजियों वाले रिकॉर्ड को अपडेट करते समय स्पष्ट होने का औचित्य केवल स्ट्रिंग प्रकारों (varchar, आदि) पर लागू होता है, क्योंकि अन्यथा खाली स्ट्रिंग को डिफ़ॉल्ट के रूप में पारित किया जा सकता है। यह MySQL के मामले में है, और अद्यतन पर एक अखंडता त्रुटि का परिणाम है।
कोडमैंटल

4

हाँ, यह काम करेगा जैसा कि आप इसे करने की उम्मीद करते हैं। दुर्भाग्य से, मुझे MySQL मैनुअल में इसका स्पष्ट विवरण खोजने में परेशानी हो रही है ।

विदेशी कुंजी का मतलब है कि मूल्य अन्य तालिका में मौजूद होना चाहिए। NULL का अर्थ मूल्य की अनुपस्थिति से है, इसलिए जब आप NULL को एक कॉलम सेट करते हैं, तो इससे कोई अड़चन नहीं आएगी।


डिज़ाइन द्वारा विदेशी कुंजी को कुछ कुंजी (प्राथमिक) का उल्लेख करना चाहिए जो NULL नहीं है, लेकिन विकास के चरण के दौरान जब हमें पहले बच्चे के टेबल में कई डेटा डालने की आवश्यकता होती है, जिसे हम नहीं जानते कि यह किसके लिए (मूल तालिका) संदर्भित करेगा । इसीलिए हमारे पास NULL मान की अनुमति है। उत्पादन में NULL का डिज़ाइन प्रवाह होगा, जिसे मोटे तौर पर कहा जा सकता है।
विमल कृत

2

ऊपर काम करता है लेकिन यह नहीं करता है। DELETE CASCADE पर ध्यान दें

CREATE DATABASE t;
USE t;

CREATE TABLE parent (id INT NOT NULL,
                 PRIMARY KEY (id)
) ENGINE=INNODB;

CREATE TABLE child (id INT NULL, 
                parent_id INT NULL,
                FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE

) ENGINE=INNODB;


INSERT INTO child (id, parent_id) VALUES (1, NULL);
-- Query OK, 1 row affected (0.01 sec)

4
'उपरोक्त' से आपका क्या तात्पर्य है? ध्यान दें कि यदि आप किसी अन्य उत्तर का संदर्भ दे रहे हैं तो क्रम बदल सकता है।
d219

2

हां, मान NULL हो सकता है, लेकिन आपको स्पष्ट होना चाहिए। मैंने पहले भी ऐसी ही स्थिति का अनुभव किया है, और ऐसा होना आसान क्यों है, और इसलिए यह याद रखने में थोड़ा समय लगता है कि क्या किया जाना चाहिए।

यदि जमा किया गया डेटा खाली स्ट्रिंग के रूप में डाला या व्याख्या किया जाता है, तो वह विफल हो जाएगा। हालाँकि, INSERTING या UPDATING के दौरान NULL के मान को स्पष्ट रूप से सेट करके, आप जाना अच्छा समझते हैं।

लेकिन यह प्रोग्रामिंग का मज़ा है, है ना? हमारी अपनी समस्याएँ बनाना और फिर उन्हें ठीक करना! चीयर्स!


1

इसके चारों ओर एक और तरीका दूसरी तालिका में DEFAULT तत्व सम्मिलित करना होगा। उदाहरण के लिए, किसी अन्य तालिका पर uuid = 00000000-0000-0000-0000-000000000000 का कोई भी संदर्भ इंगित नहीं करेगा। आपको उस आईडी के लिए "न्यूट्रल" होने के लिए सभी मान सेट करने की आवश्यकता है, उदाहरण के लिए, 0, खाली स्ट्रिंग, शून्य इस कोड लॉजिक को प्रभावित नहीं करने के लिए।


2
यह एक ही बात नहीं है। एक डिफ़ॉल्ट या "तटस्थ" मान NULL के समान नहीं है, मान का अभाव। एक NULL से अधिक डिफ़ॉल्ट मान की योग्यता पर चर्चा किए बिना, आपका वाक्यांश एक लिट्टी मिश्रित है। "इसके चारों ओर एक और तरीका दूसरी तालिका में एक अशक्त तत्व सम्मिलित करना होगा" कुछ और कहना चाहिए जैसे "इसके चारों ओर एक और तरीका एक अन्य तालिका में DEFAULT तत्व सम्मिलित करना होगा"
अंधभक्ति

0

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

CREATE TABLE parent (
   id int(10) UNSIGNED NOT NULL,
    PRIMARY KEY (id)
) ENGINE=INNODB;

CREATE TABLE child (
    id int(10) UNSIGNED NOT NULL,
    parent_id int(10) UNSIGNED DEFAULT NULL,
    FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE
) ENGINE=INNODB;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.