2009-05-20 18 views
130

क्या आप SQL Server 2000 में तालिका चर पर एक अनुक्रमणिका बना सकते हैं?तालिका चर पर एक अनुक्रमणिका बनाना

अर्थात

DECLARE @TEMPTABLE TABLE (
     [ID] [int] NOT NULL PRIMARY KEY 
     ,[Name] [nvarchar] (255) COLLATE DATABASE_DEFAULT NULL 
) 

मैं नाम पर एक सूचकांक बना सकता हूँ?

+3

दोनों प्रकार की अस्थायी तालिकाओं को बनाने में लागत है; और यदि आपके पास इतना डेटा है कि आपको एक अनुक्रमणिका की आवश्यकता है तो वास्तविक समय का उपयोग करने के लिए समय हो सकता है; कि आप लेनदेन सुरक्षित होने के लिए स्थापित; स्पिड या उपयोगकर्ता आईडी द्वारा फ़िल्टर करें और फिर अंत में इसे साफ़ करें। असली टेबल v temp टेबल दोनों में अप और डाउन हैं लेकिन यदि प्रदर्शन एक मुद्दा है; एक असली मेज के साथ भी कोशिश करें। – u07ch

+0

एक अस्थायी तालिका 'आईएस' एक वास्तविक तालिका है, जब आप कर लेंगे तो यह दूर हो जाता है। असली अंतर (इसके अलावा स्वचालित रूप से दूर हो जाएगा) यह है कि यह TempDB में है। इंडेक्स और बाधाओं की बात आती है जब यह वास्तव में बड़ा होता है क्योंकि आप अपने कोड के अन्य निष्पादन के साथ ही आपके उदाहरण में अन्य डेटाबेस में निष्पादित कोड के साथ नाम संघर्ष के साथ समाप्त हो सकते हैं। – bielawski

+0

@bielawski यह एक तालिका चर नहीं है एक temp तालिका। तालिका चर स्पष्ट रूप से नामित बाधाओं की अनुमति नहीं देते हैं, सिस्टम उत्पन्न नाम अद्वितीय होने की गारंटी देते हैं।वे 2014 से अनुक्रमित अनुक्रमों की अनुमति देते हैं लेकिन यह कोई समस्या नहीं है क्योंकि इंडेक्स को केवल ऑब्जेक्ट के भीतर विशिष्ट रूप से नामित करने की आवश्यकता नहीं है। –

उत्तर

256

प्रश्न SQL Server 2000 टैग किया गया है लेकिन नवीनतम संस्करण पर विकसित लोगों के लाभ के लिए मैं इसे पहले संबोधित करूंगा।

SQL सर्वर 2014

बाधा आधारित अनुक्रमणिका SQL सर्वर 2014 नीचे चर्चा जोड़ने के तरीकों के अलावा भी अनुमति देता है गैर अद्वितीय अनुक्रमणिका तालिका चर घोषणाओं पर इनलाइन वाक्य रचना के साथ सीधे निर्दिष्ट किया जाना है।

इसके लिए उदाहरण वाक्यविन्यास नीचे है।

/*SQL Server 2014+ compatible inline index syntax*/ 
DECLARE @T TABLE (
C1 INT INDEX IX1 CLUSTERED, /*Single column indexes can be declared next to the column*/ 
C2 INT INDEX IX2 NONCLUSTERED, 
     INDEX IX3 NONCLUSTERED(C1,C2) /*Example composite index*/ 
); 

छानने अनुक्रमित और शामिल कॉलम के साथ अनुक्रमित वर्तमान में इस वाक्य रचना तथापि एसक्यूएल सर्वर 2016 साथ घोषित नहीं किया जा सकता यह एक सा आगे को आराम। सीटीपी 3.1 से अब तालिका चर के लिए फ़िल्टर किए गए इंडेक्स घोषित करना संभव है। 2012

मैं एक बना सकते हैं - द्वारा आरटीएम यह मामले भी शामिल है कि स्तंभ भी अनुमति दी जाती है लेकिन मौजूदा स्थिति यह है कि वे "will likely not make it into SQL16 due to resource constraints"

/*SQL Server 2016 allows filtered indexes*/ 
DECLARE @T TABLE 
(
c1 INT NULL INDEX ix UNIQUE WHERE c1 IS NOT NULL /*Unique ignoring nulls*/ 
) 

SQL Server 2000 हो सकता है नाम पर सूचकांक?

संक्षिप्त उत्तर: हां।

DECLARE @TEMPTABLE TABLE (
    [ID] [INT] NOT NULL PRIMARY KEY, 
    [Name] [NVARCHAR] (255) COLLATE DATABASE_DEFAULT NULL, 
    UNIQUE NONCLUSTERED ([Name], [ID]) 
) 

एक और विस्तृत उत्तर नीचे दिया गया है।

SQL सर्वर में पारंपरिक टेबल या तो क्लस्टर्ड इंडेक्स हो सकता है या heaps के रूप में संरचित किया जा सकता है।

क्लस्टर्ड इंडेक्स को या तो डुप्लिकेट कुंजी मानों को अस्वीकार करने या गैर अद्वितीय के लिए डिफ़ॉल्ट के रूप में घोषित किया जा सकता है। यदि अद्वितीय नहीं है तो SQL सर्वर चुपचाप uniqueifier को अद्वितीय बनाने के लिए किसी भी डुप्लिकेट कुंजी में जोड़ता है।

गैर क्लस्टर इंडेक्स को भी स्पष्ट रूप से अद्वितीय घोषित किया जा सकता है। अन्यथा गैर अद्वितीय केस SQL ​​सर्वर adds the row locator (क्लस्टरर्ड इंडेक्स कुंजी या RID एक ढेर के लिए) सभी इंडेक्स कुंजियों (केवल डुप्लिकेट नहीं) के लिए यह सुनिश्चित करता है कि वे अद्वितीय हैं।

SQL सर्वर 2000 - 2012 तालिका चरों पर इंडेक्स केवल UNIQUE या PRIMARY KEY बाधा बनाकर अंतर्निहित रूप से बनाया जा सकता है। इन बाधाओं के प्रकारों के बीच अंतर यह है कि प्राथमिक कुंजी गैर शून्य कॉलम पर होनी चाहिए। एक अद्वितीय बाधा में भाग लेने वाले कॉलम शून्य हो सकते हैं। (हालांकि NULL एस की उपस्थिति में अद्वितीय बाधाओं का SQL सर्वर का कार्यान्वयन SQL मानक में निर्दिष्ट नहीं है)। इसके अलावा एक तालिका में केवल एक प्राथमिक कुंजी हो सकती है लेकिन कई अद्वितीय बाधाएं हो सकती हैं।

इन दोनों तार्किक बाधाओं को शारीरिक रूप से एक अद्वितीय अनुक्रमणिका के साथ कार्यान्वित किया जाता है। स्पष्ट रूप से अन्यथा निर्दिष्ट नहीं हैं PRIMARY KEY क्लस्टर सूचकांक बन जाएगा और अद्वितीय की कमी गैर क्लस्टर लेकिन इस व्यवहार बाधा घोषणा के साथ स्पष्ट रूप से CLUSTERED या NONCLUSTERED को निर्दिष्ट (उदाहरण वाक्य रचना)

DECLARE @T TABLE 
(
A INT NULL UNIQUE CLUSTERED, 
B INT NOT NULL PRIMARY KEY NONCLUSTERED 
) 

ऊपर के परिणामस्वरूप द्वारा अधिरोहित जा सकता है निम्नलिखित अनुक्रमित परोक्ष एसक्यूएल सर्वर में तालिका चर पर बनाया जा सकता है 2000 - 2012.

+-------------------------------------+-------------------------------------+ 
|    Index Type    | Can be created on a table variable? | 
+-------------------------------------+-------------------------------------+ 
| Unique Clustered Index    | Yes         | 
| Nonunique Clustered Index   |          | 
| Unique NCI on a heap    | Yes         | 
| Non Unique NCI on a heap   |          | 
| Unique NCI on a clustered index  | Yes         | 
| Non Unique NCI on a clustered index | Yes         | 
+-------------------------------------+-------------------------------------+ 

पिछले एक स्पष्टीकरण का एक सा की आवश्यकता है। इस की शुरुआत में तालिका चर परिभाषा में Name पर गैर अद्वितीय गैर संकुल अनुक्रमणिका का जवाब Name,Id पर एक अद्वितीय सूचकांक से प्रेरित है (कि एसक्यूएल सर्वर याद चुपचाप वैसे भी गैर अद्वितीय NCI कुंजी करने के लिए क्लस्टर सूचकांक कुंजी जोड़ना होगा)।

एक अद्वितीय अद्वितीय क्लस्टरर्ड इंडेक्स को एक अद्वितीय निर्माता के रूप में कार्य करने के लिए मैन्युअल रूप से IDENTITY कॉलम जोड़कर हासिल किया जा सकता है।

DECLARE @T TABLE 
(
A INT NULL, 
B INT NULL, 
C INT NULL, 
Uniqueifier INT NOT NULL IDENTITY(1,1), 
UNIQUE CLUSTERED (A,Uniqueifier) 
) 

लेकिन यह कैसे एक गैर अनन्य संकुल अनुक्रमणिका सामान्य रूप से वास्तव में एसक्यूएल सर्वर में लागू किया जाएगा के रूप में इस सभी पंक्तियों के लिए "Uniqueifier" कहते हैं की एक सटीक अनुकरण नहीं है। न सिर्फ उन लोगों की आवश्यकता है।

+1

नोट: 2000-2012 समाधान केवल तभी काम करता है जब टेक्स्ट कॉलम <= 900 बाइट्स हो। अर्थात। वर्कर (900), nvarchar (450) –

+1

@AndreFigueiredo हाँ, यह उन संस्करणों में स्थायी तालिकाओं पर इंडेक्स कुंजी के लिए अधिकतम आकार है। –

+0

मैं सिर्फ यह ध्यान रखना चाहता था कि SQL 2014 उत्तर Azure में अच्छी तरह से काम करता है। धन्यवाद मार्टिन! – Jaxidian

11

यह समझा जाना चाहिए कि प्रदर्शन दृष्टिकोण से @temp टेबल और #temp सारणी के बीच कोई अंतर नहीं है जो चर के पक्ष में हैं। वे एक ही स्थान (tempdb) में रहते हैं और उसी तरह लागू होते हैं। सभी अंतर अतिरिक्त सुविधाओं में दिखाई देते हैं। यह आश्चर्यजनक पूर्ण लेखन देखें: https://dba.stackexchange.com/questions/16385/whats-the-difference-between-a-temp-table-and-table-variable-in-sql-server/16386#16386

हालांकि ऐसे मामले हैं जहां तालिका या स्केलर फ़ंक्शंस में एक अस्थायी तालिका का उपयोग नहीं किया जा सकता है, v2016 से पहले अन्य मामलों के लिए (जहां फ़िल्टर किए गए इंडेक्स को किसी तालिका में जोड़ा जा सकता है परिवर्तनीय) आप बस एक #temp तालिका का उपयोग कर सकते हैं।

tempdb में नामित इंडेक्स (या बाधाओं) का उपयोग करने की कमी यह है कि नाम तब संघर्ष कर सकते हैं। न केवल सैद्धांतिक रूप से अन्य प्रक्रियाओं के साथ बल्कि प्रक्रिया के अन्य उदाहरणों के साथ अक्सर आसानी से आसानी से जो एक ही इंडेक्स को #temp तालिका की प्रतिलिपि पर रखने का प्रयास करेगा।

नाम संघर्ष से बचने के लिए कुछ इस तरह आम तौर पर काम करता है:

declare @cmd varchar(500)='CREATE NONCLUSTERED INDEX [ix_temp'+cast(newid() as varchar(40))+'] ON #temp (NonUniqueIndexNeeded);'; 
exec (@cmd); 

यह सुनिश्चित करता है नाम हमेशा भी इसी प्रक्रिया का एक साथ फांसी के बीच अद्वितीय है।

+0

वर्चर (40) के बाद इसमें एक गायब ब्रैकेट है, –

+0

नामित इंडेक्स के साथ कोई समस्या नहीं है - इंडेक्स को केवल तालिका में विशिष्ट रूप से नामित किया जाना चाहिए। समस्या नामित बाधाओं के साथ है और सबसे अच्छा समाधान आम तौर पर उन्हें temp तालिकाओं में नामित नहीं करना है - नाम की बाधाएं temp तालिका ऑब्जेक्ट कैशिंग को रोकती हैं। –

+0

यह केवल कुछ संस्करणों के लिए सत्य होना चाहिए (यदि यह किसी भी संस्करण के लिए सच है)। मुझे विशेष रूप से इस कार्यवाही के साथ आना पड़ा क्योंकि मैंने एक साथ निष्पादन के दौरान नामित इंडेक्स के संघर्ष में एसपी असफलताओं का पता लगाया था। – bielawski