SQL सर्वर में एक अद्वितीय सूचकांक और एक प्राथमिक कुंजी के बीच चयन करने की एक विधि है?
कम से कम प्राथमिक कुंजी को संदर्भित करने के लिए SqlServer को निर्देशित करना संभव है, जब विदेशी कुंजी बनाई जा रही है और वैकल्पिक कुंजी की कमी या अद्वितीय अनुक्रमित तालिका को संदर्भित किया जा रहा है।
यदि प्राथमिक कुंजी को संदर्भित करने की आवश्यकता है, तो संदर्भित तालिका के केवल नाम को विदेशी कुंजी परिभाषा में निर्दिष्ट किया जाना चाहिए और संदर्भित किए जा रहे स्तंभों की सूची को छोड़ दिया जाना चाहिए:
ALTER TABLE Child
ADD CONSTRAINT FK_Child_Parent FOREIGN KEY (ParentID)
-- omit key columns of the referenced table
REFERENCES Parent /*(ParentID)*/;
अधिक विवरण नीचे।
निम्नलिखित सेटअप पर विचार करें:
CREATE TABLE T (id int NOT NULL, a int, b int, c uniqueidentifier, filler binary(1000));
CREATE TABLE TRef (tid int NULL);
जहाँ तालिका TRef
संदर्भ तालिका के लिए अभिप्रेत है T
।
संदर्भ संबंधी बाधा पैदा करने के लिए कोई व्यक्ति ALTER TABLE
दो विकल्पों के साथ कमांड का उपयोग कर सकता है :
ALTER TABLE TRef
ADD CONSTRAINT FK_TRef_T_1 FOREIGN KEY (tid) REFERENCES T (id);
ALTER TABLE TRef
ADD CONSTRAINT FK_TRef_T_2 FOREIGN KEY (tid) REFERENCES T;
ध्यान दें कि दूसरे मामले में संदर्भित की जा रही तालिका के कोई कॉलम निर्दिष्ट नहीं हैं ( REFERENCES T
बनाम REFERENCES T (id)
)।
चूंकि T
अभी तक कोई प्रमुख सूचकांक नहीं हैं, इसलिए इन आदेशों का निष्पादन त्रुटियों को उत्पन्न करेगा।
पहली कमांड त्रुटि के बाद लौटती है:
सुश्री 1776, स्तर 16, राज्य 0, पंक्ति 4
संदर्भित तालिका 'T' में कोई प्राथमिक या उम्मीदवार कुंजी नहीं हैं जो विदेशी कुंजी 'FK_TRef_T_1' में संदर्भित स्तंभ सूची से मेल खाती हैं।
हालाँकि, दूसरा कमांड अलग त्रुटि देता है:
सुश्री 1773, स्तर 16, राज्य 0, पंक्ति 4
विदेशी कुंजी 'FK_TRef_T_2' में ऑब्जेक्ट 'T' का निहितार्थ होता है, जिस पर प्राथमिक कुंजी परिभाषित नहीं होती है।
देखें कि पहले मामले में उम्मीद प्राथमिक या उम्मीदवार कुंजी है , जबकि दूसरे मामले में उम्मीद केवल प्राथमिक कुंजी है ।
चलो जांचते हैं कि SqlServer दूसरी कमांड के साथ प्राथमिक कुंजी के अलावा कुछ और का उपयोग करेगा या नहीं।
यदि हम कुछ विशिष्ट अनुक्रमित और अद्वितीय कुंजी जोड़ते हैं T
:
CREATE UNIQUE INDEX IX_T_1 on T(id) INCLUDE (filler);
CREATE UNIQUE INDEX IX_T_2 on T(id) INCLUDE (c);
CREATE UNIQUE INDEX IX_T_3 ON T(id) INCLUDE (a, b);
ALTER TABLE T
ADD CONSTRAINT UQ_T UNIQUE CLUSTERED (id);
FK_TRef_T_1
निर्माण के लिए आदेश सफल होता है, लेकिन FK_TRef_T_2
सृजन के लिए आदेश अभी भी Msg 1773 के साथ विफल रहता है।
अंत में, यदि हम प्राथमिक कुंजी जोड़ते हैं T
:
ALTER TABLE T
ADD CONSTRAINT PK_T PRIMARY KEY NONCLUSTERED (id);
FK_TRef_T_2
निर्माण के लिए आदेश सफल होता है।
आइए देखें कि तालिका की T
विदेशी कुंजियों द्वारा तालिका के किन अनुक्रमों को संदर्भित किया जाता है TRef
:
select
ix.index_id,
ix.name as index_name,
ix.type_desc as index_type_desc,
fk.name as fk_name
from sys.indexes ix
left join sys.foreign_keys fk on
fk.referenced_object_id = ix.object_id
and fk.key_index_id = ix.index_id
and fk.parent_object_id = object_id('TRef')
where ix.object_id = object_id('T');
यह रिटर्न:
index_id index_name index_type_desc fk_name
--------- ----------- ----------------- ------------
1 UQ_T CLUSTERED NULL
2 IX_T_1 NONCLUSTERED FK_TRef_T_1
3 IX_T_2 NONCLUSTERED NULL
4 IX_T_3 NONCLUSTERED NULL
5 PK_T NONCLUSTERED FK_TRef_T_2
देखें कि इसके FK_TRef_T_2
अनुरूप PK_T
।
तो, हाँ, REFERENCES T
वाक्यविन्यास विदेशी कुंजी के उपयोग के साथ TRef
प्राथमिक कुंजी को मैप किया जाता है T
।
मैं सीधे SqlServer प्रलेखन में वर्णित ऐसे व्यवहार को खोजने में सक्षम नहीं था, लेकिन समर्पित Msg 1773 से पता चलता है कि यह आकस्मिक नहीं है। इस तरह के कार्यान्वयन से SQL मानक का अनुपालन होता है, नीचे ANSI / ISO 9075-2: 2003 की धारा 11.8 से छोटा अंश है
11 स्कीमा परिभाषा और हेरफेर
11.8 <संदर्भ संबंधी बाधा परिभाषा>
समारोह
एक निर्देशात्मक बाधा निर्दिष्ट करें।
स्वरूप
<referential constraint definition> ::=
FOREIGN KEY <left paren> <referencing columns> <right paren>
<references specification>
<references specification> ::=
REFERENCES <referenced table and columns>
[ MATCH <match type> ]
[ <referential triggered action> ]
...
सिंटेक्स नियम
...
3) केस:
...
बी) यदि <संदर्भित तालिका और कॉलम> एक <संदर्भ कॉलम सूची> निर्दिष्ट नहीं करता है, तो संदर्भित तालिका के तालिका विवरणक में एक अद्वितीय बाधा शामिल होगी जो प्राथमिक कुंजी निर्दिष्ट करती है। बता दें कि संदर्भित कॉलम उस विशिष्ट बाधा में अद्वितीय स्तंभों द्वारा पहचाने जाने वाले स्तंभ या स्तंभ हैं और संदर्भित स्तंभ
एक ऐसा स्तंभ है। <संदर्भित तालिका और कॉलम> को स्पष्ट रूप से एक <संदर्भ स्तंभ सूची> निर्दिष्ट करना माना जाएगा, जो कि <अद्वितीय स्तंभ सूची> के समान है।
...
Transact-SQL ANSI SQL को सपोर्ट करता है और बढ़ाता है। हालाँकि यह SQL मानक के अनुरूप नहीं है। SQL Server Transact-SQL ISO / IEC 9075-2 स्टैंडर्ड सपोर्ट डॉक्यूमेंट (MS-TSQLISO02 संक्षेप में, यहां देखें ) नाम का एक दस्तावेज है जो Transact-SQL द्वारा प्रदान किए गए समर्थन के स्तर का वर्णन करता है। दस्तावेज़ मानक के लिए एक्सटेंशन और विविधताओं को सूचीबद्ध करता है। उदाहरण के लिए यह दस्तावेज है कि MATCH
क्लॉज़ को संदर्भात्मक बाधा परिभाषा में समर्थित नहीं किया गया है। लेकिन मानक के उद्धृत टुकड़े के लिए प्रासंगिक कोई प्रलेखित विविधताएं नहीं हैं। इसलिए, मेरी राय है कि मनाया गया व्यवहार पर्याप्त रूप से प्रलेखित है।
और के उपयोग के साथ REFERENCES T (<reference column list>)
वाक्यविन्यास के ऐसा लगता है कि SqlServer तालिका के अनुक्रमित के बीच पहले उपयुक्त गैर-अनुक्रमित सूचकांक का चयन करता है (जिसे कम से कम index_id
प्रतीत होता है, प्रश्न के टिप्पणियों में ग्रहण किए गए सबसे छोटे भौतिक आकार के साथ नहीं), या क्लस्टर सूचकांक यदि यह सूट और कोई उपयुक्त गैर-अनुक्रमित सूचकांक नहीं हैं। ऐसा व्यवहार SqlServer 2008 (संस्करण 10.0) के बाद से सुसंगत प्रतीत होता है। यह केवल पाठ्यक्रम का अवलोकन है, इस मामले में कोई गारंटी नहीं है।