2009-01-23 15 views
50

को पहचान सेट मैं एक मेज पर पहचान रीसेट करने के लिए इस कोड का उपयोग कर रहा हूँ:बी सी सी CHECKIDENT 0

DBCC CHECKIDENT('TableName', RESEED, 0) 

यह ठीक समय के सबसे अधिक काम करता है, पहली डालने मैं ईद स्तंभ में 1 डालने के साथ । हालांकि अगर मैं डीबी छोड़ देता हूं और इसे फिर से बना देता हूं (स्क्रिप्ट्स का उपयोग करके मैंने लिखा है) और फिर डीबीसीसी चेचकेंट को कॉल करें, तो डाली गई पहली वस्तु में 0 की एक आईडी होगी।

कोई विचार?

संपादित करें: शोध करने के बाद मुझे पता चला कि मैं ठीक से दस्तावेज़ पढ़ें नहीं किया:। http://msdn.microsoft.com/en-us/library/aa258817(SQL.80).aspx - "वर्तमान पहचान मूल्य new_reseed_value पर सेट है यदि कोई भी पंक्ति तालिका में सम्मिलित किया गया है के बाद से यह बनाया गया था, पहली पंक्ति को क्रियान्वित बी सी सी CHECKIDENT पहचान के रूप में new_reseed_value का उपयोग करेगा के बाद सम्मिलित किया गया। अन्यथा, अगली पंक्ति new_reseed_value + 1. "

उत्तर

17

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

हटाने का बजाए तालिका को साफ करने के लिए ट्रंकेट का उपयोग करने का एक संभावित समाधान है। लेकिन फिर आपको सभी बाधाओं को छोड़ने और उन्हें बाद में फिर से बनाने की आवश्यकता है

इस तरह यह हमेशा एक नव निर्मित तालिका के रूप में व्यवहार करता है और डीबीसीसी अध्यक्ष को कॉल करने की आवश्यकता नहीं होती है। पहले पहचान मूल्य एक तालिका परिभाषा में निर्दिष्ट किया जाएगा और यदि आप पहली बार के लिए या भी यहाँ एन वें

+1

यह लिंक लगता है मृत होने के लिए, वर्तमान दस्तावेज https://msdn.microsoft.com/en-us/library/ms176057.aspx कहता है कि 2012 से पहले के संस्करणों के लिए केवल अपेक्षित व्यवहार है, लेकिन यह सच नहीं लगता है (परीक्षण 2012 संस्करण पर, संगतता 2012 तक सेट, अभी भी समस्या देख रही है)। – jmoreno

5

बयान बदलें

DBCC CHECKIDENT('TableName', RESEED, 1) 

के लिए प्रयोग करेंगे डाला इस से शुरू कर देंगे 2 (या 1 whe n आप तालिका को फिर से बनाते हैं), लेकिन यह कभी भी 0

1

देखें के लिए डेटा सम्मिलित यह कोई फर्क नहीं पड़ता ही होगा: http://sqlblog.com/blogs/alexander_kuznetsov/archive/2008/06/26/fun-with-dbcc-chekident.aspx

यह दस्तावेज व्यवहार है, यदि आप तालिका को फिर से बनाते हैं, तो आप चैककिडेंट क्यों चलाते हैं, उस मामले में चरण छोड़ें या TRUNCATE का उपयोग करें (यदि आपके पास एफके रिश्तों नहीं हैं)

42

आप जो भी लिखते हैं उसमें आप सही हैं सवाल।

DBCC CHECKIDENT('TableName', RESEED, 0) चलाने के बाद:
- नव निर्मित टेबल पहचान के साथ शुरू होगा 0
- मौजूदा टेबल पहचान के साथ जारी रहेगा 1

समाधान नीचे लिपि में है, यह एक गरीब-मनुष्य-truncate की तरह है :)

-- Remove all records from the Table 
DELETE FROM TableName 

-- Use sys.identity_columns to see if there was a last known identity value 
-- for the Table. If there was one, the Table is not new and needs a reset 
IF EXISTS (SELECT * FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = 'TableName' AND last_value IS NOT NULL) 
    DBCC CHECKIDENT (TableName, RESEED, 0); 
+1

बहुत अच्छा लेकिन एकाधिक स्कीमा से निपटने पर आप तालिका के नाम को देखने के लिए 'OBJECT_NAME()' का उपयोग करने के बजाय 'object_id' पर मिलान करने के लिए थोड़ा सा ट्विक करना चाहते हैं: 'अगर EXISTS (चयन * sys.identity_columns से जहां object_id = OBJECT_ID ('Schema.TableName') और last_value न्यूल नहीं है ') – Nick

1

मैंने इसे 0 के मान को रीसेट करने के लिए एक प्रयोग के रूप में किया क्योंकि मैं अपना पहला पहचान कॉलम 0 होना चाहता हूं और यह काम कर रहा है।

dbcc CHECKIDENT(MOVIE,RESEED,0) 
dbcc CHECKIDENT(MOVIE,RESEED,-1) 
DBCC CHECKIDENT(MOVIE,NORESEED) 
1
USE AdventureWorks2012; 
GO 
DBCC CHECKIDENT ('Person.AddressType', RESEED, 0); 
GO 



AdventureWorks2012=Your databasename 
Person.AddressType=Your tablename 
1

मैं एसक्यूएल में इस का इस्तेमाल किया है एक विशेष मूल्य के लिए पहचान स्थापित करने के लिए: -

DECLARE @ID int = 42; 
DECLARE @TABLENAME varchar(50) = 'tablename' 

DECLARE @SQL nvarchar(1000) = 'IF EXISTS (SELECT * FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = '''[email protected]+''' AND last_value IS NOT NULL) 
    BEGIN 
     DBCC CHECKIDENT('[email protected]+', RESEED,' + CONVERT(VARCHAR(10),@ID-1)+'); 
    END 
    ELSE 
    BEGIN 
     DBCC CHECKIDENT('[email protected]+', RESEED,' + CONVERT(VARCHAR(10),@ID)+'); 
    END'; 
EXEC (@SQL); 

और सी # में यह एक विशेष मान सेट करने के: -

SetIdentity(context, "tablename", 42); 
. 
. 
private static void SetIdentity(DbContext context, string table,int id) 
{ 
    string str = "IF EXISTS (SELECT * FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = '" + table 
     + "' AND last_value IS NOT NULL)\nBEGIN\n"; 
    str += "DBCC CHECKIDENT('" + table + "', RESEED," + (id - 1).ToString() + ");\n"; 
    str += "END\nELSE\nBEGIN\n"; 
    str += "DBCC CHECKIDENT('" + table + "', RESEED," + (id).ToString() + ");\n"; 
    str += "END\n"; 
    context.Database.ExecuteSqlCommand(str); 
} 

यह उपरोक्त उत्तरों पर बनाता है और हमेशा सुनिश्चित करता है कि अगला मान 42 है (इस मामले में)।

0

यह हास्यास्पद लगता है कि तालिका के रिकॉर्ड्स डाले गए हैं या नहीं, दोनों मामलों को कवर करने के लिए आप एक ही कॉलम के साथ एक पहचान कॉलम सेट/रीसेट नहीं कर सकते हैं। मैं उस व्यवहार को समझ नहीं पाया जब तक मैं एसओ पर उपरोक्त प्रश्न में ठोकर नहीं लगाता! मेरा समाधान - बदसूरत लेकिन काम करता है - स्पष्ट रूप से sys.identity_columns.last_value तालिका को जांचने के लिए है जो आपको बताता है कि तालिका में रिकॉर्ड्स डाले गए हैं या नहीं, और प्रत्येक मामले में उचित डीबीसीसी चेचकिड कमांड को कॉल करें: DECLARE @last_value INT = CONVERT(INT, (SELECT last_value FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = 'MyTable')); IF @last_value IS NULL BEGIN -- Table newly created and no rows inserted yet; start the IDs off from 1 DBCC CHECKIDENT ('MyTable', RESEED, 1); END ELSE BEGIN -- Table has rows; ensure the IDs continue from the last ID used DECLARE @lastValUsed INT = (SELECT ISNULL(MAX(ID),0) FROM MyTable); DBCC CHECKIDENT ('MyTable', RESEED, @lastValUsed); END

संबंधित मुद्दे