NULL कॉलम पर एक अद्वितीय इंडेक्स कैसे बनाएं?


101

मैं SQL Server 2005 का उपयोग कर रहा हूं। मैं NULLS की अनुमति देते हुए मानों को एक कॉलम में विशिष्ट करने के लिए विवश करना चाहता हूं।

मेरे वर्तमान समाधान में इस तरह के दृश्य पर एक अद्वितीय सूचकांक शामिल है:

CREATE VIEW vw_unq WITH SCHEMABINDING AS
    SELECT Column1
      FROM MyTable
     WHERE Column1 IS NOT NULL

CREATE UNIQUE CLUSTERED INDEX unq_idx ON vw_unq (Column1)

कोई बेहतर विचार?


16
एसक्यूएल 2008 का उपयोग करने का कोई मौका नहीं? आप 'जहां' का उपयोग करके एक फ़िल्टर किया हुआ सूचकांक बना सकते हैं
सिमोन_विवर

3
आपको अद्वितीय का मतलब नहीं था , NULLs की अनुमति देने से , आपको लगता है कि अद्वितीय का मतलब है, लेकिन कई NULLs भी शामिल हैं । अन्यथा, NULL को किसी अन्य मान की तरह अनुक्रमित किया जाता है और विशिष्टता की बाधा अपेक्षित रूप से काम करती है - SQL मानकों के अनुसार नहीं, जैसा कि @pst ने नीचे टिप्पणी में उल्लेख किया है।
Suncat2000

जवाबों:


26

बहुत यकीन है कि आप ऐसा नहीं कर सकते, क्योंकि यह uniques के उद्देश्य का उल्लंघन करता है।

हालाँकि, इस व्यक्ति को आस-पास एक अच्छा काम लगता है: http://sqlservercodebook.blogspot.com/2008/04/multiple-null-values-in-unique-index-in.html


2
ऐसा लगता है कि आपके द्वारा प्रदत्त लिंक की सामग्री वास्तव में (आंशिक रूप से) यहां से बिना किसी
अटेंशन के

77
मैं असहमत हूं कि यह "uniques के उद्देश्य का उल्लंघन करता है" - NULL SQL में एक विशेष मूल्य है (NaN के कई तरीकों के समान) और तदनुसार इलाज की आवश्यकता है। यह वास्तव में विभिन्न SQL विशिष्टताओं को सम्मानित करने के लिए SQL सर्वर में विफलता है: यहां "सही कार्यान्वयन" के लिए एक अनुरोध के लिए एक लिंक है जो इसके लायक है: connect.microsoft.com/SQLServer/feedback/details/299229/…

5
2008 में संदर्भ के लिए आप dbo.bar (कुंजी) पर UNIQUE INDEX foo बना सकते हैं, जहां कुंजी पूरी नहीं है;
नीको

2
मैं इससे सहमत नहीं हूं कि "अनकांशस के उद्देश्य का उल्लंघन करता है", NULL NULL के बराबर नहीं है, इसलिए आपको nullable कॉलम पर अद्वितीय इंडेक्स बनाने और कई nulls डालने में सक्षम होना चाहिए।
वोडज़ू

105

SQL Server 2008 का उपयोग करके, आप एक फ़िल्टर किए गए इंडेक्स बना सकते हैं: http://msdn.microsoft.com/en-us/library/cc280372.aspx । (मैं देख रहा हूं कि साइमन ने इसे एक टिप्पणी के रूप में जोड़ा था, लेकिन यह सोचा था कि यह अपने जवाब के योग्य है क्योंकि टिप्पणी आसानी से याद आती है।)

एक अन्य विकल्प विशिष्टता की जांच करने के लिए एक ट्रिगर है, लेकिन यह प्रदर्शन को प्रभावित कर सकता है।


84
create unique index UIX on MyTable (Column1) where Column1 is not null
जॉर्न शॉ-रोड

1
नोट: वर्तमान में SQL सर्वर प्रबंधन स्टूडियो को यह पता नहीं लगता है कि इस तरह के इंडेक्स कैसे बनाए जाते हैं इसलिए यदि आप बाद में टेबल को संशोधित करते हैं तो यह भ्रमित हो जाएगा और इसे छोड़ने की कोशिश करें ताकि इसे पुनः बनाने के लिए याद रखें
Simon_Weaver

3
ऐसा लगता है कि Microsoft ने इसका समर्थन करने के लिए SSMS को अपडेट किया है। मेरे पास SSMS 10.50.1617 है और सूचकांक गुण संवाद में आप फ़िल्टर को संपादित करने के लिए फ़िल्टर पृष्ठ का चयन कर सकते हैं। उदाहरण के लिए "([
कॉलम

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

यदि आप किसी फ़िल्टर किए गए अनुक्रमणिका के साथ तालिका पर संग्रहीत कार्यविधियों का उपयोग कर रहे हैं, तो सुनिश्चित करें कि वह ANSI_NULLSहै ON, अन्यथा डेटा सम्मिलित करने का प्रयास करते समय आपको एक त्रुटि मिलेगी।
Arne

71

गणना की गई स्तंभ चाल को व्यापक रूप से एक "नलबास्टर" के रूप में जाना जाता है; मेरे नोट्स क्रेडिट स्टीव कास:

CREATE TABLE dupNulls (
pk int identity(1,1) primary key,
X  int NULL,
nullbuster as (case when X is null then pk else 0 end),
CONSTRAINT dupNulls_uqX UNIQUE (X,nullbuster)
)

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

@DavidStorfer, आप ऐसा नहीं कर सकते क्योंकि आप दो अलग-अलग तालिकाओं की आईडी के बीच टकराव हो सकता है।
1839 पर उपयोगकर्ता393274

सुधार: ISNULL (X, CONVERT (VARCHAR (10), pk))
Faiz

5
@ फैज़: सुधार देखने वाले की नज़र में है। मुझे ओरिजिनल का लुक पसंद है।
onedaywhen

@NunoG, यह स्वीकृत उत्तर होना चाहिए क्योंकि यह आपकी आवश्यकताओं के अनुरूप एक अच्छा समाधान प्रदान करता है, इसके बजाय केवल एक बाहरी साइट को लिंक करना जो गायब हो सकती है।
Frédéric

-3

सख्ती से बोलना, एक अद्वितीय अशक्त स्तंभ (या स्तंभों का समूह) केवल एक बार NULL (या NULLs का रिकॉर्ड) हो सकता है, क्योंकि एक ही मूल्य (और इसमें NULL शामिल है) एक से अधिक बार स्पष्ट रूप से अद्वितीय बाधा का उल्लंघन करता है।

हालांकि, इसका मतलब यह नहीं है कि "अद्वितीय नल योग्य कॉलम" की अवधारणा वैध है; वास्तव में इसे किसी भी संबंधपरक डेटाबेस में लागू करने के लिए हमें बस यह ध्यान रखना है कि इस तरह के डेटाबेस को ठीक से काम करने के लिए सामान्यीकृत किया जाए, और सामान्यीकरण में आमतौर पर संस्थाओं के बीच संबंध स्थापित करने के लिए कई (गैर-इकाई) अतिरिक्त तालिकाओं को शामिल किया जाता है। ।

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

मान लीजिए कि हम एक तालिका द्वारा प्रस्तुत की गई जानकारी इस तरह से हैं:

create table the_entity_incorrect
(
  id integer,
  uniqnull integer null, /* we want this to be "unique and nullable" */
  primary key (id)
);

हम ऐसा नहीं कर सकते uniqnull को अलग करके और uniqnull मानों के बीच एक संबंध स्थापित करने के लिए दूसरी तालिका जोड़कर the_entity ("the_entity के अंदर uniqnull" होने के बजाय):

create table the_entity
(
  id integer,
  primary key(id)
);

create table the_relation
(
  the_entity_id integer not null,
  uniqnull integer not null,

  unique(the_entity_id),
  unique(uniqnull),
  /* primary key can be both or either of the_entity_id or uniqnull */
  primary key (the_entity_id, uniqnull), 
  foreign key (the_entity_id) references the_entity(id)
);

The_entity में हमें एक पंक्ति में uniqnull के मान को जोड़ने के लिए हमें the_relation में एक पंक्ति भी जोड़ने की आवश्यकता है।

In_entity में पंक्तियाँ नहीं थीं क्योंकि कोई भी असंबद्ध मान जुड़े नहीं हैं (अर्थात हम जिन्हें NULL__ityity_incorrect में डालेंगे) हम केवल the_relation में एक पंक्ति नहीं जोड़ते हैं।

ध्यान दें कि uniqnull के लिए मान सभी the_relation के लिए अद्वितीय होंगे, और यह भी ध्यान दें कि in_entity में प्रत्येक मान के लिए the_relation में अधिकतम एक मान हो सकता है, क्योंकि इस पर प्राथमिक और विदेशी कुंजियाँ इसे लागू करती हैं।

फिर, अगर uniqnull के लिए 5 का मान 3 की a_entity आईडी के साथ जुड़ा होना है, तो हमें इसकी आवश्यकता होगी:

start transaction;
insert into the_entity (id) values (3); 
insert into the_relation (the_entity_id, uniqnull) values (3, 5);
commit;

और, अगर the_entity के लिए 10 की आईडी वैल्यू के लिए कोई अनइकनाल समकक्ष नहीं है, तो हम केवल यह करते हैं:

start transaction;
insert into the_entity (id) values (10); 
commit;

इस जानकारी को निरूपित करने और डेटा को the_entity_incorrect की तरह एक तालिका प्राप्त करने के लिए, हमें निम्न की आवश्यकता होगी:

select
  id, uniqnull
from
  the_entity left outer join the_relation
on
  the_entity.id = the_relation.the_entity_id
;

"लेफ्ट आउटर जॉइन" ऑपरेटर सुनिश्चित करता है कि the_entity की सभी पंक्तियाँ परिणाम में दिखाई देंगी, NULL को यूनीकनल कॉलम में रखें जब कोई मिलान कॉलम the_relation में मौजूद न हो।

याद रखें, एक अच्छी तरह से सामान्यीकृत डेटाबेस (और इसी तरह के विचारों और प्रक्रियाओं को डिजाइन करने में) कुछ दिनों (या हफ्तों या महीनों) के लिए खर्च किए गए किसी भी प्रयास से आपको दर्द और व्यर्थ संसाधनों के वर्षों (या दशकों) की बचत होगी।


6
जैसा कि पहले से ही पचास अपवोट्स के साथ स्वीकृत उत्तर की टिप्पणी पर कहा गया है, इसे MS Sql सर्वर द्वारा समर्थित होना चाहिए ताकि अद्वितीय के रूप में अनुक्रमित कॉलम में कई अशक्त हों। यह अनुमति नहीं देने के लिए SQL मानकों को लागू करने में विफलता है। अशक्त मूल्य नहीं है, अशक्त शून्य के बराबर नहीं है, यह वर्षों से एक बुनियादी SQL नियम है। इसलिए आपका पहला वाक्य गलत है और अधिकांश पाठक इसे पढ़ने से परेशान नहीं होंगे।
Frédéric
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.