अशक्त विदेशी कुंजी बुरा अभ्यास?


114

मान लें कि आपके पास ग्राहक आईडी में एक विदेशी कुंजी के साथ एक तालिका आदेश है। अब, मान लीजिए कि आप एक ग्राहक आईडी के बिना ऑर्डर जोड़ना चाहते हैं, (क्या यह संभव होना चाहिए एक और सवाल है) आपको विदेशी कुंजी को पूरा करना होगा ... क्या यह बुरा अभ्यास है या आप इसके बीच लिंक टेबल के साथ काम करेंगे आदेश और ग्राहक? हालांकि संबंध 1 से n है, एक लिंक तालिका इसे n से n तक बना देगी। दूसरी ओर, लिंक टेबल के साथ, मेरे पास अब उन नल नहीं हैं ...

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

(मेरे मामले में यह ऑर्डर और ग्राहक नहीं है)।

EDIT: लिंक करने के लिए एक बिना ग्राहक के बारे में क्या?


9
यह NULLs डेटाबेस स्कीमा में उपलब्ध होने के मुख्य उद्देश्यों में से एक है। इसके अलावा, इसीलिए आप फ़ील्ड को NULL या NOT NULL घोषित कर सकते हैं, ताकि आपके स्कीमा की विशिष्ट आवश्यकताओं को पूरा किया जा सके।
गहोआ

7
मैंने शुरू में इस प्रश्न को अशक्त प्राथमिक कुंजियों के रूप में पढ़ा , और कुछ मजबूत सलाह के साथ उतारा था ... :-)
आंद्रेज डॉयल

जवाबों:


51

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

एक और बात; लिंक टेबल का उपयोग करना जरूरी नहीं है कि यह n से n तक हो, यदि आप लिंक टेबल में उस विदेशी कुंजी का उपयोग करते हैं जो आपके ऑर्डर टेबल की ओर इशारा कर रही है क्योंकि लिंक टेबल में प्राथमिक कुंजी संबंध अभी भी 1..n है। प्रति आदेश तालिका में केवल एक प्रविष्टि हो सकती है।


2
source__destination_link या SourceDestination
Svisstack

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

5
जैसा कि मेरे उत्तर में बताया गया है कि मैं इस विशिष्ट मामले में व्यावहारिक हूँ और लिंक तालिका का उपयोग नहीं करूँगा। मुझे यकीन है कि सामान्य रूपों का आविष्कार प्रक्रिया प्रवाह में सुधार करने के लिए नहीं किया गया था, बल्कि निरंतरता सुनिश्चित करने और अतिरेक से बचने के लिए किया गया था। हालांकि यह एक बहुत ही सामान्य चर्चा है, मुझे लगता है कि इसे एक मामले के आधार पर देखा जाना चाहिए।
पेट्रिक हैगने

110

नहीं, Nullable FKs में कुछ भी गलत नहीं है। यह तब सामान्य होता है जब प्राथमिक कुंजी संदर्भ तालिका के साथ एफके अंक एक (शून्य या एक) में (1 या कई) संबंध में होता है।

एक उदाहरण हो सकता है यदि आपके पास एक तालिका में भौतिक पता और मेलिंग पता विशेषता (स्तंभ) दोनों हैं, जिसमें एफके के साथ एक पता तालिका है। आप भौतिक पते को संभाल सकने योग्य बना सकते हैं जब इकाई में केवल पोस्ट ऑफिस बॉक्स (मेलिंग एड्रेस) हो, और मेलिंग एड्रेस जब भौतिक पते (या नहीं) के समान हो तो संभाल करने के लिए मेल करने योग्य पता।


39

अशक्त स्तंभ 1NF में 5NF के माध्यम से हो सकते हैं, लेकिन मैंने जो पढ़ा है, उसके अनुसार 6NF में नहीं।

केवल अगर आप क्रिस डेट से बेहतर जानते हैं "वास्तव में पहला सामान्य रूप क्या है"। यदि x और y दोनों अशक्त हैं, और वास्तव में कुछ पंक्ति में x और y दोनों हैं null, तो WHERE x=yउपज नहीं होती है true। यह उचित संदेह से परे साबित होता है कि अशक्त मूल्य नहीं है (क्योंकि कोई भी वास्तविक मूल्य हमेशा खुद के बराबर होता है)। और जब से आरएम ने निर्धारित किया है कि "तालिका के प्रत्येक कक्ष में एक मूल्य होना चाहिए", किसी भी चीज में संभवतः नल होते हैं, एक संबंधपरक बात नहीं है, और इस प्रकार 1NF का सवाल भी नहीं उठता है।

मैंने सुना है कि सामान्य रूप से अशक्त स्तंभ सामान्यीकरण की पहली डिग्री को तोड़ देते हैं।

उस तर्क को अंतर्निहित ध्वनि कारण के लिए ऊपर देखें।

लेकिन व्यवहार में यह बहुत व्यावहारिक है।

केवल तभी यदि आप सिरदर्द से प्रतिरक्षा रखते हैं जो आमतौर पर दुनिया के बाकी हिस्सों में होता है। ऐसा एक सिरदर्द (और यह केवल एक मामूली है, तुलनात्मक रूप से अन्य nullघटनाओं के लिए) तथ्य यह है किWHERE x=y एसक्यूएल वास्तव में इसका मतलब है WHERE x is not null and y is not null and x=y, लेकिन यह कि ज्यादातर प्रोग्रामर केवल उस तथ्य से अवगत नहीं होते हैं और बस उस पर पढ़ते हैं। कभी-कभी बिना किसी नुकसान के, दूसरी बार नहीं।

वास्तव में, अशक्त कॉलम सबसे मौलिक डेटाबेस डिज़ाइन नियमों में से एक का उल्लंघन करते हैं: एक कॉलम में अलग-अलग सूचना तत्वों को संयोजित नहीं करते हैं। नल ठीक वैसा ही करते हैं क्योंकि वे बूलियन मूल्य को संयोजित करते हैं "यह फ़ील्ड वास्तविक मूल्य के साथ वास्तव में मौजूद नहीं है / है"।


18
+1 के लिए "जहां x शून्य नहीं है और y शून्य नहीं है और x = y" नहीं है। उस के बारे में पता नहीं था।
रॉब

1
बहुत अच्छी तरह से तर्क और उदाहरण दिया।
पेड्ज़ २५'१४

1
एक समस्या। जब मान "अस्तित्व में नहीं होता है" (जो एक वास्तविक दुनिया का परिदृश्य है), और डेटाबेस विशेषता शून्य को अनुमति नहीं देता है, जो भी मूल्य विशेषता में है वह गलत है। सिर दर्द के रूप में, याद है, KISS, यह न सिर्फ मतलब रखें यह आसान है, यह संभव के रूप में सरल है, लेकिन कोई सरल रूप में यह रखें इसका मतलब है। यदि "रिलेशनल मॉडल" को अवास्तविक, बेवकूफ परिणाम की आवश्यकता होती है, तो शायद वास्तविक दुनिया के डेटा को संभालने के लिए नियमों का विस्तार करने की आवश्यकता है?
चार्ल्स ब्रेटाना

1
यह दिखाया गया है कि एक थ्री-वैल्यूड लॉजिक पाँच-वैल्यूड लॉजिक, आदि आदि के लिए चार-वैल्यूड लॉजिक के लिए एक की जरूरत पर ले जाया जाता है, और एक की जरूरत है कि सुराग 2-वैल्यूड लॉजिक है पर्याप्त है, लेकिन डेटा संरचनाओं हम जब मिलता है इसे लागू करना "जितना संभव हो उतना सरल" अभी भी कम से कम सरल है "जितना हम चाहते हैं उतना सरल"।
इरविन स्मौट

2
क्रिस तिथि, तर्क और डेटाबेस, अध्याय 6, "क्यों संबंधपरक DBMS तर्क कई-मूल्यवान नहीं होना चाहिए", पृष्ठ 145। उस अध्याय के संदर्भों की सूची भी दिलचस्प होनी चाहिए, विशेष रूप से मैकगवरन को शामिल करने वाले।
एरविन स्मट

13

मैं कुछ भी गलत नहीं देख सकता कि यह सिर्फ एक वैकल्पिक n-1 संबंध है जिसे विदेशी-कुंजी में एक अशक्तता के साथ दर्शाया जाएगा। अन्यथा यदि आप अपना लिंक टेबल रखते हैं तो आपको यह प्रबंध करना होगा कि यह एक nn संबंध न बने, इसलिए और भी अधिक परेशानी का कारण होगा।


2
वास्तव में यह 0-N संबंध है, वैकल्पिक 1-N संबंध नहीं। लेकिन मैं तुमसे सहमत हूँ।
एरिक जे।

5
प्रबंधित करें? यह 0 से 1 के पक्ष में एक सरल UNIQUE बाधा है!
wqw

2
हाँ, यह एक अड़चन है, लेकिन आपको उस अड़चन के कारण बाद में अपने कोड में संभावित अपवादों से भी
जूझना पड़ेगा

4

संबंधपरक मॉडल में वैकल्पिक संबंध निश्चित रूप से संभव हैं।

आप एक रिश्ते की अनुपस्थिति को व्यक्त करने के लिए नल का उपयोग कर सकते हैं। वे सुविधाजनक हैं, लेकिन वे आपको वही सिरदर्द पैदा करेंगे जो नल आपको कहीं और करते हैं। एक जगह जहां वे किसी भी परेशानी का कारण नहीं बनते हैं वे जुड़ते हैं। विदेशी कुंजियों में अशक्त होने वाली पंक्तियाँ संदर्भित तालिका में किसी भी पंक्तियों से मेल नहीं खाती हैं। इसलिए वे एक आंतरिक जुड़ाव छोड़ देते हैं। यदि आप बाहरी जुड़ाव करते हैं, तो आप वैसे भी नल से निपटने जा रहे हैं।

यदि आप वास्तव में नल (6 वें सामान्य रूप) से बचना चाहते हैं, तो आप तालिका को विघटित कर सकते हैं। दो विघटित तालिकाओं में से एक में दो विदेशी कुंजी स्तंभ हैं। एक आपके पास वैकल्पिक विदेशी कुंजी है, और दूसरी मूल तालिका की प्राथमिक कुंजी को संदर्भित करने वाली एक विदेशी कुंजी है। अब आपको रिश्तों को कई-कई बनने से रोकने के लिए बाधाओं का उपयोग करना होगा, आप इसे रोकना चाहते हैं।


2

अपूर्ण आदेशों को साफ करने के लिए NULL का उपयोग करना एक अच्छा तरीका होगा:

SELECT * FROM `orders`
WHERE `started_time` < (UNIX_TIMESTAMP() + 900) AND `customer_id` IS NULL

उपरोक्त ग्राहक संबंधित आईडी के बिना 15 मिनट से अधिक पुराने आदेश दिखाएगा।


1

यदि आप केवल ग्राहक के परिभाषित होने तक कोई ग्राहक आईडी के साथ अस्थायी रूप से ऑर्डर जोड़ रहे हैं, तो क्या ग्राहक और ऑर्डर को एक ही लेनदेन में जोड़ना सरल नहीं होगा, जिससे NULL विदेशी कुंजी प्रविष्टि की आवश्यकता को दूर करने और किसी भी बाधा या ट्रिगर से बचने की आवश्यकता होगी आपने उल्लंघन किया है?

आम तौर पर यह स्थिति उन वेब एप्स के रूप में सामने आती है जहां ग्राहक को यह निर्धारित करने से पहले कि वह कौन है, यह आदेश विस्तृत है। और उन स्थितियों में ऑर्डर को सर्वर स्थिति या कुकी में रखा जाता है जब तक कि एक पूर्ण ऑर्डर के लिए सभी आवश्यक स्थिति की आपूर्ति उस बिंदु पर नहीं की जाती है जब तक कि ऑर्डर डेटाबेस पर कायम रहता है।

उपर्युक्त बताए अनुसार पतों जैसी चीजों के लिए पूर्ण विदेशी कुंजियाँ ठीक हैं। लेकिन एक पूर्ण ग्राहक क्षेत्र एक आदेश के लिए कोई मतलब नहीं है और विवश होना चाहिए।


आदेश-ग्राहक एक उदाहरण के रूप में था। मेरे ऐप में यह पते की तरह अधिक idd है। तुरंत एक उदाहरण नहीं मिल सकता है जो सभी तरह से सही था। धन्यवाद।
लेवेन कार्डोन नोव

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

1

आप हमेशा अपने ग्राहक तालिका में एक कृत्रिम पंक्ति जोड़ सकते हैं, जैसे कि Id = -1 और CustomerName = 'अज्ञात' और फिर ऐसे मामलों में जब आप सामान्य रूप से अपने CustomerId को सेट करेंगे क्रम NULL में इसे -1 पर सेट करें।

यह आपको कोई अशक्त FKs की अनुमति नहीं देता है, लेकिन फिर भी उचित रूप से डेटा की कमी का प्रतिनिधित्व करता है (और आपको डाउनस्ट्रीम उपयोगकर्ताओं को NULLs से निपटने का तरीका नहीं जानने से बचाएगा)।


बस इसे जोड़ने के लिए, याद रखें कि NULLS एक इंडेक्स (ओरेकल) में संग्रहीत नहीं होता है, इसलिए इसका मतलब है कि लिंक तालिका को छोड़ना और अशक्त FK के लिए जाने से समझदारी का प्रदर्शन होगा। दूसरी बात यह निर्भर कर सकती है कि क्या आप इस लिंक टेबल में कुछ और स्टोर करना चाहते हैं, उदाहरण के लिए, डब्ल्यूएचओ ने क्या लिंक बनाया है और कब? क्या लिंक अब निष्क्रिय / हटा दिया गया है (लेकिन एक बार था?)
वॉर्थी

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

0

वैकल्पिक कई-से-एक संबंधों के लिए अशक्त FKs पूरी तरह से ठीक हैं।


-1

मैंने सुना है कि सामान्य रूप से अशक्त स्तंभ सामान्यीकरण की पहली डिग्री को तोड़ते हैं। लेकिन व्यवहार में यह बहुत व्यावहारिक है।


3
अशक्त स्तंभ 1NF में 5NF के माध्यम से हो सकते हैं, लेकिन मैंने जो पढ़ा है, उसके अनुसार 6NF में नहीं।
वाल्टर मिती

-1

हाँ कुछ गलत है। यह एक विदेशी कुंजी नहीं है अगर इसकी अशक्त है। इसका डेटाबेस डिजाइन कोड द्वारा। हो सकता है कि आप बिना हस्ताक्षर किए शून्य लिंक करें। या "अनसाइन्टेड" यदि आपका एक चरित्र कॉल का उपयोग कर रहा है। अपने डेटा की अखंडता को 100% रखें।

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