Sqlserver
 sql >> डेटाबेस >  >> RDS >> Sqlserver

अनुक्रम में अगला नंबर कैसे प्राप्त करें

यदि आप काउंटर टेबल नहीं रखते हैं, तो दो विकल्प हैं। लेन-देन के भीतर, पहले MAX(seq_id) . चुनें निम्न तालिका संकेतों में से एक के साथ:

  1. WITH(TABLOCKX, HOLDLOCK)
  2. WITH(ROWLOCK, XLOCK, HOLDLOCK)

TABLOCKX + HOLDLOCK थोड़ा अधिक है। यह नियमित चुनिंदा बयानों को अवरुद्ध करता है, जिन्हें भारी . माना जा सकता है भले ही लेन-देन छोटा हो।

एक ROWLOCK, XLOCK, HOLDLOCK तालिका संकेत शायद एक बेहतर विचार है (लेकिन:काउंटर टेबल के साथ विकल्प को आगे पढ़ें)। इसका लाभ यह है कि यह नियमित चयन कथनों को अवरुद्ध नहीं करता है, अर्थात जब चयन कथन SERIALIZABLE में प्रकट नहीं होते हैं लेन-देन, या जब चयन कथन समान तालिका संकेत प्रदान नहीं करते हैं। ROWLOCK, XLOCK, HOLDLOCK का उपयोग करना अभी भी इन्सर्ट स्टेटमेंट को ब्लॉक कर देगा।

निश्चित रूप से आपको यह सुनिश्चित करने की आवश्यकता है कि आपके प्रोग्राम का कोई अन्य भाग MAX(seq_id) का चयन न करे इन तालिका संकेतों के बिना (या SERIALIZABLE . के बाहर लेन-देन) और फिर पंक्तियों को सम्मिलित करने के लिए इस मान का उपयोग करें।

ध्यान दें कि इस तरह से लॉक की गई पंक्तियों की संख्या के आधार पर, यह संभव है कि SQL सर्वर लॉक को टेबल लॉक में बढ़ा देगा। लॉक एस्केलेशन के बारे में अधिक पढ़ें यहां

WITH(ROWLOCK, XLOCK, HOLDLOCK) का उपयोग करते हुए डालने की प्रक्रिया इस प्रकार दिखेगा:

DECLARE @target_model INT=3;
DECLARE @part VARCHAR(128)='Spine';
BEGIN TRY
    BEGIN TRANSACTION;
    DECLARE @max_seq INT=(SELECT MAX(seq) FROM dbo.table_seq WITH(ROWLOCK,XLOCK,HOLDLOCK) WHERE [email protected]_model);
    IF @max_seq IS NULL SET @max_seq=0;
    INSERT INTO dbo.table_seq(part,seq,model)VALUES(@part,@max_seq+1,@target_model);
    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    ROLLBACK TRANSACTION;
END CATCH

काउंटर . रखना एक वैकल्पिक और शायद एक बेहतर विचार है तालिका, और ये तालिका संकेत काउंटर टेबल पर प्रदान करें। यह तालिका निम्न की तरह दिखेगी:

CREATE TABLE dbo.counter_seq(model INT PRIMARY KEY, seq_id INT);

फिर आप डालने की प्रक्रिया को इस प्रकार बदलेंगे:

DECLARE @target_model INT=3;
DECLARE @part VARCHAR(128)='Spine';
BEGIN TRY
    BEGIN TRANSACTION;
    DECLARE @new_seq INT=(SELECT seq FROM dbo.counter_seq WITH(ROWLOCK,XLOCK,HOLDLOCK) WHERE [email protected]_model);
    IF @new_seq IS NULL 
        BEGIN SET @new_seq=1; INSERT INTO dbo.counter_seq(model,seq)VALUES(@target_model,@new_seq); END
    ELSE
        BEGIN SET @new_seq+=1; UPDATE dbo.counter_seq SET [email protected]_seq WHERE [email protected]_model; END
    INSERT INTO dbo.table_seq(part,seq,model)VALUES(@part,@new_seq,@target_model);
    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    ROLLBACK TRANSACTION;
END CATCH

लाभ यह है कि कम पंक्ति ताले का उपयोग किया जाता है (अर्थात dbo.counter_seq में प्रति मॉडल एक ), और लॉक एस्केलेशन पूरे dbo.table_seq . को लॉक नहीं कर सकता तालिका इस प्रकार चुनिंदा बयानों को अवरुद्ध करती है।

WAITFOR DELAY '00:01:00' डालकर आप इन सबका परीक्षण कर सकते हैं और स्वयं प्रभाव देख सकते हैं। counter_seq . से अनुक्रम का चयन करने के बाद , और दूसरे SSMS टैब में तालिका (तालिकाओं) के साथ फ़िदा होना।

PS1:ROW_NUMBER() OVER (PARTITION BY model ORDER BY ID) का उपयोग करना अच्छा तरीका नहीं है। यदि पंक्तियों को हटा दिया जाता है/जोड़ दिया जाता है, या आईडी बदल जाती है तो अनुक्रम बदल जाएगा (इनवॉइस आईडी पर विचार करें जो कभी नहीं बदलना चाहिए)। प्रदर्शन के मामले में भी एक पंक्ति को पुनर्प्राप्त करते समय पिछली सभी पंक्तियों की पंक्ति संख्या निर्धारित करना एक बुरा विचार है।

PS2:मैं लॉकिंग प्रदान करने के लिए बाहरी संसाधनों का कभी भी उपयोग नहीं करूंगा, जब SQL सर्वर पहले से ही आइसोलेशन स्तर या फाइन-ग्रेन्ड टेबल संकेतों के माध्यम से लॉकिंग प्रदान करता है।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. डेटाबेस + विंडोज प्रमाणीकरण + उपयोगकर्ता नाम/पासवर्ड?

  2. क्या EXISTS को सीधे बिट के रूप में चुनना संभव है?

  3. SQL सर्वर में पहचान () फ़ंक्शन का उपयोग कैसे करें

  4. कई कैस्केड पथ उत्पन्न करने वाले कैस्केडिंग हटाता है

  5. SQL सर्वर (T-SQL उदाहरण) में 'datetime2' को 'time' में बदलें