तकनीकी रूप से, NULL = NULL गलत है, उस तर्क से कोई NULL किसी भी NULL के बराबर नहीं है और सभी NULL अलग हैं। इस का अर्थ यह नहीं है कि सभी NULLs अद्वितीय हैं और एक अद्वितीय सूचकांक NULLs की किसी भी संख्या को अनुमति देना चाहिए?
तकनीकी रूप से, NULL = NULL गलत है, उस तर्क से कोई NULL किसी भी NULL के बराबर नहीं है और सभी NULL अलग हैं। इस का अर्थ यह नहीं है कि सभी NULLs अद्वितीय हैं और एक अद्वितीय सूचकांक NULLs की किसी भी संख्या को अनुमति देना चाहिए?
जवाबों:
यह इस तरह से काम क्यों करता है? क्योंकि जिस तरह से वापस, किसी ने बिना किसी डिजाइन या निर्णय के परवाह किए कि मानक क्या कहता है (आखिरकार, हमारे पास NULL
एस के साथ सभी प्रकार के अजीब व्यवहार हैं , और इच्छा पर अलग व्यवहार कर सकते हैं)। यही कारण है कि निर्णय तय करती है कि, में इस मामले NULL = NULL
।
यह एक बहुत ही स्मार्ट निर्णय नहीं था। उन्हें जो करना चाहिए था वह एएनएसआई मानक का पालन करने के लिए डिफ़ॉल्ट व्यवहार है, और यदि वे वास्तव में इस अजीब व्यवहार को चाहते हैं, तो इसे डीडीएल विकल्प जैसे WITH CONSIDER_NULLS_EQUAL
या के माध्यम से अनुमति दें WITH ALLOW_ONLY_ONE_NULL
।
निश्चित रूप से, 20/20 की बाधा है।
और हमारे पास एक वर्कअराउंड है, अब, वैसे भी, भले ही यह सबसे साफ या सबसे सहज न हो।
आप SQL Server 2008 और इसके बाद के संस्करण में एक अद्वितीय, फ़िल्टर किए गए अनुक्रमणिका बनाकर उचित ANSI व्यवहार प्राप्त कर सकते हैं।
CREATE UNIQUE INDEX foo ON dbo.bar(key) WHERE key IS NOT NULL;
यह एक से अधिक NULL
मूल्य की अनुमति देता है क्योंकि उन पंक्तियों को डुप्लिकेट चेकिंग से पूरी तरह से छोड़ दिया जाता है। एक अतिरिक्त बोनस के रूप में, यह एक छोटी अनुक्रमणिका के रूप में होता है, जिसमें एक से अधिक तालिकाएँ होती हैं यदि एकाधिक NULL
s की अनुमति होती है (विशेषकर जब यह सूचकांक में एकमात्र स्तंभ नहीं होता है, तो इसमें INCLUDE
कॉलम आदि होते हैं)। हालाँकि, आप फ़िल्टर्ड अनुक्रमित की कुछ अन्य सीमाओं से अवगत होना चाहते हैं:
सही बात। Sql सर्वर में एक अद्वितीय बाधा या सूचकांक के कार्यान्वयन से एक और केवल एक NULL की अनुमति मिलती है। यह भी सही है कि यह तकनीकी रूप से NULL की परिभाषा के साथ फिट नहीं है, लेकिन यह उन चीजों में से एक है, जिन्होंने इसे "तकनीकी रूप से" सही नहीं होने के बावजूद इसे और अधिक उपयोगी बनाने के लिए किया। ध्यान दें एक प्राथमिक कुंजी (एक अद्वितीय सूचकांक भी) NULLs (बेशक) की अनुमति नहीं देता है।
पहला - "अशक्त मूल्य" वाक्यांश का उपयोग करना बंद करें, यह आपको भटका देगा। इसके बजाय, वाक्यांश "अशक्त मार्कर" का उपयोग करें - एक स्तंभ में एक मार्कर जो यह दर्शाता है कि इस स्तंभ में वास्तविक मूल्य या तो गायब है या अनुपयुक्त है (लेकिन ध्यान दें कि मार्कर यह नहीं कहता है कि वास्तव में उन विकल्पों में से कौन सा मामला है)।
अब, निम्नलिखित की कल्पना करें (जहां डेटाबेस को मॉडलिंग की स्थिति का पूरा ज्ञान नहीं है)।
Situation Database
ID Code ID Code
-- ----- -- -----
1 A 1 A
2 B 2 (null)
3 C 3 C
4 B 4 (null)
अखंडता नियम जो हम मॉडलिंग कर रहे हैं वह है "कोड अद्वितीय होना चाहिए"। वास्तविक दुनिया की स्थिति इसका उल्लंघन करती है, इसलिए डेटाबेस को आइटम 2 और 4 दोनों को एक ही समय में तालिका में नहीं रखने देना चाहिए।
सबसे सुरक्षित और कम से कम लचीला, दृष्टिकोण कोड क्षेत्र में अशक्त मार्करों को अस्वीकार करना होगा, इसलिए असंगत डेटा की कोई संभावना नहीं है। सबसे लचीला दृष्टिकोण कई शून्य मार्करों की अनुमति देना और मूल्यों में प्रवेश करने पर विशिष्टता के बारे में चिंता करना होगा।
सिबेस के प्रोग्रामर टेबल में केवल एक अशक्त मार्कर की अनुमति देने के लिए कुछ हद तक सुरक्षित, नहीं-बहुत-लचीले दृष्टिकोण के साथ गए - कुछ टिप्पणीकारों ने तब से शिकायत की है। Microsoft ने इस व्यवहार को जारी रखा है, मुझे लगता है कि पश्चगामी संगतता है।
Two मुझे यकीन है कि मैंने कहीं पढ़ा है कि कॉड ने दो अशक्त मार्करों को लागू करने पर विचार किया - एक अज्ञात के लिए, एक अनुपयुक्त के लिए - लेकिन इसे अस्वीकार कर दिया, लेकिन मुझे संदर्भ नहीं मिल रहा है। क्या मुझे सही याद है?
PS मेरा पसंदीदा उद्धरण अशक्त के बारे में: लुई डेविडसन, "प्रोफेशनल SQL सर्वर 2000 डेटाबेस डिज़ाइन", Wrox प्रेस, 2001, पृष्ठ 52. "एक वाक्य के लिए उबला हुआ: NULL बुराई है।"
null
यह लक्ष्य प्राप्त नहीं होता है। क्योंकि अनुपलब्ध मान अन्य पंक्तियों में से एक मान के समान हो सकता है।
CHECK (Value IN ('A','B','C','D'))
? फिर SQL- सर्वर के कार्यान्वयन और SQL मानक दोनों तालिका को 5 पंक्तियों (NULL के साथ प्रत्येक मान 1 के लिए एक पंक्ति) की अनुमति देते हैं। फिर, यकीनन, जबकि डेटाबेस अपने अवरोधों के अनुरूप है, यह डिज़ाइनर के इरादे के अनुरूप नहीं है। तालिका में अधिकतम 4 पंक्तियाँ हैं। इसका कोई मूल्य नहीं है कि NULL को उस में बदला जा सकता है, जब तक कि एक या अधिक पंक्तियों को हटा नहीं दिया जाता, एक बाधा का उल्लंघन नहीं करेगा।
CREATE TABLE #T(A INT NULL UNIQUE);INSERT INTO #T VALUES (1),(NULL);UPDATE #T SET A = 1 WHERE A IS NULL;
कोई त्रुटि उठाएगा। आपके द्वारा डिजाइन किए गए प्रेरणा के सिद्धांत के अनुसार NULL
पहले मामले में सम्मिलन को रोकना चाहिए - क्योंकि अपूर्ण ज्ञान का अर्थ है कि कोई गारंटी नहीं है कि मूल्य अलग है।
यह तकनीकी रूप से सटीक नहीं हो सकता है, लेकिन दार्शनिक रूप से यह मुझे रात में सोने में मदद करता है ...
जैसे कई अन्य ने कहा है या के लिए कहा गया है, यदि आप NULL को अज्ञात मानते हैं, तो आप यह निर्धारित नहीं कर सकते कि एक NULL मान वास्तव में दूसरे NULL मान के बराबर है या नहीं। इसे इस तरह से सोचकर, NULL == NULL को NULL का मूल्यांकन करना चाहिए, जिसका अर्थ अज्ञात है।
स्तंभ मानों की तुलना के लिए एक अद्वितीय बाधा को एक निश्चित मान की आवश्यकता होगी। दूसरे शब्दों में, समानता ऑपरेटर का उपयोग करके किसी भी अन्य स्तंभ मान के खिलाफ एकल स्तंभ मान की तुलना करते समय, इसे मान्य होने के लिए गलत का मूल्यांकन करना होगा। अज्ञात वास्तव में गलत नहीं है भले ही इसे अक्सर झूठा माना जाता है। दो पूर्ण मान समान हो सकते हैं, या नहीं ... यह केवल निश्चित रूप से निर्धारित नहीं किया जा सकता है।
यह एक अद्वितीय बाधा के रूप में उन मूल्यों को प्रतिबंधित करने में मदद करता है जिन्हें एक दूसरे से अलग होने के लिए निर्धारित किया जा सकता है। इसका मतलब क्या है अगर आप एक SELECT चलाते हैं जो कुछ इस तरह दिखता है:
SELECT * from dbo.table1 WHERE ColumnWithUniqueContraint="some value"
अधिकांश लोग एक परिणाम की उम्मीद करेंगे, यह देखते हुए कि एक अद्वितीय बाधा है। यदि आपने ColumnWithUniqueConstraint में एकाधिक NULL मानों को अनुमति दी है, तो NULL का उपयोग किए गए मान के रूप में तालिका से एक अलग पंक्ति का चयन करना असंभव होगा।
यह देखते हुए, मेरा मानना है कि NULL की परिभाषा के सम्मान के साथ इसे सही ढंग से लागू किया गया है या नहीं, इसकी परवाह किए बिना, यह निश्चित रूप से कई स्थितियों में कई अधिक व्यावहारिक मूल्यों की अनुमति देने की तुलना में अधिक व्यावहारिक है।
एक UNIQUE
बाधा के प्रमुख उद्देश्यों में से एक डुप्लिकेट रिकॉर्ड को रोकने के लिए है। यदि किसी को एक तालिका रखने की आवश्यकता होती है जिसमें कई रिकॉर्ड हो सकते हैं जहां एक मान "अज्ञात" है, लेकिन किसी भी दो रिकॉर्ड को समान "ज्ञात" मान रखने की अनुमति नहीं है, तो अज्ञात मानों को कृत्रिम अद्वितीय पहचानकर्ता को सौंपा जाना चाहिए। तालिका में जोड़ा गया।
कुछ दुर्लभ मामले हैं जिनमें एक स्तंभ जिसमें एक UNIQUE
बाधा होती है और एक एकल अशक्त मान होता है; उदाहरण के लिए, यदि किसी तालिका में स्तंभ मानों और स्थानीय पाठ विवरणों के बीच मानचित्रण होता है, तो उस पंक्ति NULL
को उस विवरण को परिभाषित करना संभव होगा जो किसी अन्य तालिका में उस स्तंभ के दिखाई देने पर होना चाहिए NULL
। NULL
उस उपयोग के मामले के लिए अनुमति देता है का व्यवहार ।
अन्यथा, मैं UNIQUE
कई समान अभिलेखों के अस्तित्व की अनुमति देने के लिए किसी भी स्तंभ पर एक बाधा के साथ डेटाबेस के लिए कोई आधार नहीं देखता हूं , लेकिन मुझे कई रिकॉर्डों की अनुमति देने के लिए कोई उपाय नहीं दिखता है, जिनके महत्वपूर्ण मान अलग-अलग नहीं होते हैं। यह घोषित करना कि NULL
खुद के बराबर नहीं है NULL
मूल्यों को एक दूसरे से अलग नहीं किया जाएगा ।