จำลองลำดับ TSQL ผ่านกระบวนงานที่เก็บไว้


17

ฉันมีความต้องการในการสร้างขั้นตอนการจัดเก็บซึ่งจำลองลำดับ TSQL นั่นคือจะให้ค่าจำนวนเต็มที่แตกต่างเพิ่มขึ้นทุกครั้งที่โทร นอกจากนี้หากมีการส่งจำนวนเต็มควรส่งคืนค่านั้นหากไม่เคยได้ผลลัพธ์ที่ดีกว่าหรือจำนวนเต็มที่สูงสุดถัดไปที่มีอยู่ มันไปโดยไม่บอกว่าอาจมีลูกค้าหลายรายที่เรียกใช้ SP นี้ในเวลาเดียวกัน

รับ MetaInfo ตารางพร้อมคอลัมน์ MetaKey varchar (สูงสุด) และ MeatValueLong bigInt คาดว่าแถวที่มี MetaKey ของ 'Internal-ID-Last' จะมีค่าสูงสุดที่กำหนดล่าสุด ฉันสร้างกระบวนงานที่เก็บไว้ต่อไปนี้:

CREATE PROCEDURE [dbo].[uspGetNextID]
(
  @inID bigInt 
)
AS
BEGIN
    SET NOCOUNT ON;

    BEGIN TRANSACTION

    UPDATE MetaInfo WITH (ROWLOCK) 
      SET MetaValueLong = CASE 
                            WHEN ISNULL(MetaValueLong,0) > @inID THEN MetaValueLong+1 
                            ELSE @inID+1
                          END 
    WHERE MetaKey = 'Internal-ID-Last'

    SELECT MetaValueLong 
    FROM MetaInfo
    WHERE MetaKey = 'Internal-ID-Last'

    COMMIT TRANSACTION 

END

คำถามของฉันเป็นเพียงขั้นตอนการจัดเก็บนี้ทำงานตามที่คาดไว้ (ผู้โทรทั้งหมดจะได้รับผลลัพธ์ที่ไม่ซ้ำ)


@ ทั้งหมด: FYI, วางไข่โดย Q นี้บน SO: stackoverflow.com/q/6342732/27535
gbn

คำตอบ:


8

ฉันมีรูปลักษณ์และ MS เองก็เสนอวิธีแก้ปัญหาโดยไม่ล็อค

http://blogs.msdn.com/b/sqlcat/archive/2006/04/10/sql-server-sequence-number.aspx

นี่คือการอัปเดตอย่างง่ายโดยไม่มีคำแนะนำการล็อค แต่พวกเขาบอกว่ามันล็อค / การหยุดชะงัก

ไม่มีอะไรมากเกี่ยวกับเรื่องนี้เช่นกัน

ฉันมีแนวโน้มที่จะเพิ่ม UPDLOCK ใน ROWLOCK ของคุณ (ตาม"ตารางเป็นคิว" (SO)แต่ไม่มี READPAST) สิ่งนี้จะเพิ่มความโดดเดี่ยวในกรณีที่กระบวนการที่ 2 เริ่มอ่าน

อย่างไรก็ตามข้อเท็จจริงที่ว่ากระบวนการทั้งหมดของคุณต้องการอ่าน / เขียนแถวเดียวกันทำให้ฉันเดาตัวเองเป็นครั้งที่สอง READPAST อนุญาตให้ใช้งานพร้อมกันได้อย่างปลอดภัย แต่ในกรณีนี้มันไร้ประโยชน์

หมายเหตุ: คุณสามารถใช้ส่วนคำสั่ง OUTPUT แทนตัวเลือกที่ 2 จากนั้นคุณไม่จำเป็นต้องทำธุรกรรม

HTH ...


1
คุณเอาชนะฉันไป โปรดทราบว่า SQL Server 2011 มีฟังก์ชัน SEQUENCE ดังนั้นข้อกำหนดในการประดิษฐ์ของคุณเองควรจะหายไปในไม่ช้า (ไม่ใช่ก่อนเวลา)
nvogel

@dportas: แน่นอน และทำงานได้ดีขึ้นเช่นกัน: dba.stackexchange.com/q/1635/630
gbn

@dportas - SEQUENCE สามารถอนุญาตให้ป้อนข้อมูลได้หรือไม่ ในการอ่านคุณสมบัติอย่างรวดเร็วของฉันฉันไม่เห็นฟังก์ชันการทำงานนั้น
โฮแกน

1

สิ่งต่อไปนี้จะหายไป

1. SET XACT_ABORT
2. Exception Handling (Try Catch)

ใช่มันควรเป็นไปตามเงื่อนไขของคุณ เมื่อสถานการณ์ดังกล่าวเกิดขึ้นในการทำธุรกรรมมันจะสร้างหลายอินสแตนซ์และต่อมาผู้โทรทั้งหมดจะถูกกำหนดผลลัพธ์ที่ไม่ซ้ำ


หากฉันยืนยันก่อนการเลือกไม่มีความเป็นไปได้ที่ฉันจะเลือกผลลัพธ์ที่บันทึกไว้โดยการโทรอื่นหรือไม่
โฮแกน

ไม่แน่ใจเกี่ยวกับมัน แต่ดูเหมือนว่าคุณพูดถูก ฉันต้องตรวจสอบ ขอบคุณ BTW +1 สำหรับคำถามที่ดี ...

0

โซลูชันที่ปรับขนาดได้มากกว่าซึ่งไม่ต้องการการทำให้เป็นอนุกรมคือ:

CREATE PROCEDURE [dbo].[uspGetNextID]
(
  @inID BIGINT OUT
)
AS
      SET NOCOUNT ON
      SET IDENTITY_INSERT SequenceTable ON;
      INSERT INTO SequenceTable (id) VALUES (@inID);
      SET IDENTITY_INSERT SequenceTable OFF;
      INSERT INTO SequenceTable DEFAULT VALUES;
      DELETE FROM SequenceTable WITH (READPAST);
      SET @inID = SCOPE_IDENTITY();
RETURN;

OP มีความต้องการที่จะให้ผู้ใช้สามารถส่งผ่านค่าซึ่งมีความซับซ้อนมัน ...
GBN

@dportas - ขอบคุณ ฉันรู้วิธีนี้ แต่ไม่สามารถใช้งานได้ที่นี่เนื่องจากพารามิเตอร์อินพุต
โฮแกน

@ โฮแกนฉันได้แก้ไขข้อเสนอแนะเพื่อจัดการพารามิเตอร์อินพุต มันยังไม่ทดลองเป็นส่วนใหญ่
nvogel

@dportas - เรียกด้วย inID 500, B เรียกว่าพร้อม inID 50 - action - A ส่งคืนด้วย 51, B กับ 52 ข้อกำหนดล้มเหลว
โฮแกน

น่าสนใจ ฉันได้รับผลลัพธ์ที่แตกต่าง (วันที่ 2008r2) คุณสามารถโพสต์สำเนาเต็มด้วย DDL และระบุรุ่น / รุ่นของคุณ
nvogel
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.