2009-10-09 11 views
7

क्या एसक्यूएल (एसक्यूएल सर्वर) में किसी तालिका में किसी पहचान कॉलम से अगली आईडी (पूर्णांक) को पुनर्प्राप्त करने के लिए संभव है, और वास्तव में, बिना पंक्ति डालने के? यदि सबसे हालिया पंक्ति हटा दी गई है तो यह आवश्यक रूप से उच्चतम आईडी प्लस 1 नहीं है।कोई पंक्ति डालने के बिना अगली आईडी प्राप्त करना

मैं यह पूछता हूं क्योंकि हमें मौलिक रूप से नई पंक्तियों के साथ एक लाइव डीबी अपडेट करना होता है। पंक्ति का आईडी हमारे कोड (जैसे स्विच (आईडी) {केस आईडी:} में उपयोग किया जाता है और यह वही होना चाहिए। यदि हमारा विकास डीबी और लाइव डीबी सिंक से बाहर हो जाता है, तो पहले से ही एक पंक्ति आईडी की भविष्यवाणी करना अच्छा होगा पहले तैनाती।

मैं कर सकता के पाठ्यक्रम सेट पहचान रवाना सेट पर INSERT_IDENTITY या लेन-देन अगर वहाँ एक समारोह है कि अगले आईडी लौटे था आदि लेकिन आश्चर्य (इस रोल वापस आईडी? करता है) (incrementing के बिना यह) ।

+0

एक लेन-देन पहचान काउंटर को वापस नहीं लाएगा और इसके अलावा हर कोई थ्रेड उस नंबर का उपयोग करता है जो आपको लगता है कि आप बाद में प्राप्त करेंगे। – idstam

+0

इस @idstam के लिए धन्यवाद, मुझे इस पर संदेह था। – iWeasel

उत्तर

8

संपादित करें:

पूरे पृष्ठ डंप की तुलना घंटे के एक नंबर खर्च करने के बाद, मुझे एहसास हुआ वहाँ एक आसान तरीका है और मैं DMVs पर रहे की जाना चाहिए।

मूल्य बैकअप/पुनर्स्थापना से बचता है, जो एक स्पष्ट संकेत है कि यह संग्रहीत है - मैंने डीबी में सभी पृष्ठों को छोड़ दिया और रिकॉर्ड के दौरान स्थान/परिवर्तन नहीं मिला। पृष्ठों के 200k लाइन डंप की तुलना करना मजेदार नहीं है।

मैंने समर्पित व्यवस्थापक कंसोल का उपयोग किया था, मैंने एक पंक्ति डाली गई प्रत्येक आंतरिक तालिका का एक डंप लिया और फिर सिस्टम टेबल का एक और डंप लिया। दोनों डंप समान थे, जो इंगित करता है कि जब तक यह जीवित रहा, और इसलिए इसे संग्रहीत किया जाना चाहिए, यह उस स्तर पर भी खुलासा नहीं है।

तो एक सर्कल में घूमने के बाद मुझे एहसास हुआ कि डीएमवी का जवाब है।

create table foo (MyID int identity not null, MyField char(10)) 
insert into foo values ('test') 
go 10 

-- Inserted 10 rows 
select Convert(varchar(8),increment_value) as IncrementValue, 
    Convert(varchar(8),last_value) as LastValue 
from sys.identity_columns where name ='myid' 


-- insert another row 
insert into foo values ('test') 

-- check the values again 
select Convert(varchar(8),increment_value) as IncrementValue, 
    Convert(varchar(8),last_value) as LastValue 
from sys.identity_columns where name ='myid' 

-- delete the rows 
delete from foo 


-- check the DMV again 
select Convert(varchar(8),increment_value) as IncrementValue, 
    Convert(varchar(8),last_value) as LastValue 
from sys.identity_columns where name ='myid' 

-- value is currently 11 and increment is 1, so the next insert gets 12 
insert into foo values ('test') 
select * from foo 

Result: 
MyID  MyField 
----------- ---------- 
12   test  

(1 row(s) affected) 

सिर्फ इसलिए कि पंक्तियों को हटा दिया गया, अंतिम मान रीसेट नहीं था, इसलिए अंतिम मान + वेतन वृद्धि सही जवाब होना चाहिए।

इसके अलावा मेरे ब्लॉग पर एपिसोड लिखने जा रहा है।

ओह, और यह सब करने के लिए शॉर्टकट:

select ident_current('foo') + ident_incr('foo') 

तो यह वास्तव में पता चला है आसान होने के लिए - लेकिन यह सब मान लिया गया कोई अन्य व्यक्ति आपकी आईडी का इस्तेमाल किया है, जबकि आप इसे वापस मिल गया। जांच के लिए ठीक है, लेकिन मैं इसे कोड में उपयोग नहीं करना चाहता।

+0

यिक्स! एक उत्तर के लिए +1 जिसने मुझे मुस्कुराया – iWeasel

+0

मैंने रात भर इसका शोध किया है, सोच रहा है कि यह एक सभ्य ब्लॉग आइटम के लिए तैयार होगा, और इसे समझ लिया जाएगा। मेरा जवाब संपादित करना – Andrew

+0

@ एंड्रयू। सोचा था कि आपके हाथों पर आपके पास बहुत अधिक समय है। दूसरी तरफ एक बड़ा धन्यवाद। बहुत बढ़िया जवाब। – iWeasel

2

बल्कि एक पहचान स्तंभ का उपयोग करने से, आप एक uniqueidentifier (GUID) स्तंभ अद्वितीय पंक्ति पहचानकर्ता के रूप में अन्य विकल्प (जो मैं का उपयोग करें) का उपयोग और ज्ञात मानों डाल सकता है।

एस है ईटी IDENTITY_INSERT चालू, जहां पंक्ति आईडी को स्रोत नियंत्रित एकल 'दस्तावेज़' में प्रबंधित किया जाता है।

+1

उत्कृष्ट बिंदु, लेकिन Guids इस विशेष तालिका पर वास्तव में व्यावहारिक नहीं हैं और थोड़ा भूख लगी है। मैं इस समय IDENTITY_INSERT का उपयोग करता हूं। यह काम करता है लेकिन आश्चर्य है कि कोई विकल्प है या नहीं। :) Guids के लिए – iWeasel

+0

+1। गुड्स के पास एक ऑटो-वृद्धि कॉलम के सापेक्ष एक प्रदर्शन जुर्माना होता है (हालांकि एक पंक्ति में अतिरिक्त स्थान की आवश्यकता होती है), लेकिन वे इस तरह हुप्स के माध्यम से कूदने की आवश्यकता को पूरी तरह से खत्म कर देते हैं। – MusiGenesis

+0

जुर्माना है यदि आप GUID का उपयोग अपनी क्लस्टर कुंजी के रूप में करते हैं, तो आप प्रदर्शन और स्थान दोनों के मामले में भारी कीमत का भुगतान करते हैं। – Andrew

2

आप बहुत आसानी से तय कर सकते हैं कि अंतिम मान इस्तेमाल किया है:

SELECT 
    last_value 
FROM 
    sys.identity_columns 
WHERE 
    object_id = OBJECT_ID('yourtablename') 

आमतौर पर, अगले आईडी last_value +1 होगा - लेकिन वहाँ उस के लिए कोई गारंटी नहीं है।

मार्क

+1

निश्चित रूप से; कोई गारंटी नहीं है, इसलिए मुझे आश्चर्य हुआ कि क्या कोई विकल्प था। :) – iWeasel

+0

नहीं, कोई अन्य तरीका नहीं है - SQL सर्वर वास्तव में वास्तव में आईडी जारी करेगा जब आप वास्तव में INSERT करते हैं - इसे बनाने का कोई तरीका नहीं :-( –

2

यह थोड़ा अजीब है लेकिन यह काम करेगा:

आप अगले मूल्य पता करने के लिए, सबसे ज्यादा मूल्य के अलावा एक हो रही द्वारा शुरू करना चाहते हैं:

SELECT max(id) FROM yourtable 

करने के लिए यह काम करें, आपको सम्मिलन पर पहचान को रीसेट करने की आवश्यकता होगी:

DECLARE @value INTEGER 

SELECT @value = max(id) + 1 FROM yourtable 

DBCC CHECKIDENT (yourtable, reseed, @value) 

INSERT INTO yourtable ... 

नहीं बिल्कुल एक सुरुचिपूर्ण समाधान है लेकिन मेरे पास अभी तक मेरी कॉफी नहीं है ;-)

(यह भी मानता है कि आपकी प्रक्रिया या तालिका के पहले और दूसरे ब्लॉक के बीच किसी अन्य प्रक्रिया द्वारा तालिका में कुछ भी नहीं किया गया है)।

+0

यह सुरुचिपूर्ण नहीं हो सकता है लेकिन मैं इसे उत्तर के रूप में चिह्नित करूंगा टेबल जहां आप काफी निश्चित हो सकते हैं कि इसे चलाने से पहले कोई नई पंक्ति डाली नहीं जाती है। – iWeasel

+0

क्षमा करें जेफ, @ एंड्रयू ने पूरी रात एक उत्कृष्ट संपादन पर बिताया। एक इलाज करता है। जवाब दोबारा सौंपना होगा। – iWeasel

7

IDENT_CURRENT कोशिश:

Select IDENT_CURRENT('yourtablename') 

यह काम करता है, भले ही आप वर्तमान सत्र में किसी भी पंक्तियों सम्मिलित नहीं किया है:

एक निर्धारित तालिका या देखने के लिए उत्पन्न पिछले पहचान मान देता है । उत्पन्न अंतिम पहचान मूल्य किसी भी सत्र और किसी भी क्षेत्र के लिए हो सकता है।

+1

अच्छा।यह सबसे हालिया मूल्य का उपयोग करता है, और एमएसडीएन पेज अलर्ट करता है कि "अगली जेनरेट की गई पहचान मान की भविष्यवाणी करने के लिए IDENT_CURRENT का उपयोग करने के बारे में सावधान रहें। वास्तविक जेनरेट मान अन्य सत्रों द्वारा किए गए प्रविष्टियों के कारण IDENT_CURRENT प्लस IDENTITY_SEED से भिन्न हो सकता है।" – PaulG

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