Saklı yordam aracılığıyla bir TSQL dizisi öykünme


17

Bir TSQL dizisi taklit saklı yordam oluşturmak için bir gereksinim var. Yani her çağrıda her zaman artan bir tamsayı değeri verir. Ayrıca, bir tamsayı iletilirse, daha büyük bir sonuç veya bir sonraki en yüksek tamsayı hiç bulunmamışsa bu değeri döndürmelidir. Bu SP'yi aynı anda çağıran birden fazla müşteri olabileceğini söylemeye gerek yok.

MetaKey varchar (max) ve MeatValueLong bigInt sütunları içeren bir tablo MetaInfo verildi. 'Internal-ID-Last' MetaKey satırının, atanan son en yüksek değeri içermesi beklenir. Aşağıdaki saklı yordamı oluşturdum:

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

Sorum şu: Bu saklı yordam beklendiği gibi çalışıyor mu (tüm arayanlara benzersiz bir sonuç atanacak)?


@all: FYI, bu Q tarafından SO'da ortaya çıktı: stackoverflow.com/q/6342732/27535
gbn

Yanıtlar:


8

Bir baktım ve MS'in kendileri kilitsiz bir çözüm sunuyor

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

Bu, kilit ipucu içermeyen basit bir güncellemedir, ancak kilitlendiğini / kilitlendiğini söylüyorlar.

Bu konuda çok SO hakkında bir şey yok.

ROWLOCK'ınıza UPDLOCK eklemeye meyilli olurum ( "kuyruk olarak tabloya göre" (SO) ancak READPAST olmadan). Bu, 2. bir sürecin okumaya başlaması durumunda izolasyonu artıracaktır.

Ancak, tüm süreçlerinizin aynı satırı okumak / yazmak istemesi beni ikinci kez tahmin etmemi sağlıyor. READPAST güvenli eşzamanlılığa izin verir, ancak bu durumda işe yaramaz.

Not: 2. seçim yerine OUTPUT yantümcesini kullanabilirsiniz, sonra işleme ihtiyacınız yoktur.

HTH ...


1
Beni dövüyorsun. SQL Server 2011'in SEQUENCE işlevselliğini içerdiğini ve bu nedenle kendi icat etme gereksiniminin yakında (zamandan önce değil) ortadan kalkacağını unutmayın.
nvogel

@dportas: gerçekten. Ve daha iyi çalışır: dba.stackexchange.com/q/1635/630
gbn

@dportas - SEQUENCE giriş gereksinimine izin verebilir mi? Özelliği hızlı bir şekilde okuduğumda bu işlevselliği görmedim.
Hogan

1

Aşağıdaki şey eksik

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

Evet, durumunuzu karşılamalıdır. Bu tür durumlar işlemlere geldiğinde, Birden çok örneğini oluşturur ve daha sonra tüm arayanlara benzersiz bir sonuç atanır.


Seçimden önce taahhütte bulunursam, farklı bir çağrı tarafından kaydedilen sonucu seçebilir miyim?
Hogan

Bundan emin değilim. Ama haklısın. Kontrol etmem gerek. Teşekkürler. BTW +1 for, İyi Soru ...

0

Serileştirme gerektirmeyen daha ölçeklenebilir bir çözüm şudur:

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, kullanıcıların onu zorlaştıran bir değerden geçmelerine izin vermek için bir gereksinime sahip ...
gbn

@dportas - Teşekkürler. Bu yaklaşımın farkındaydım, ancak girdi parametresi nedeniyle burada çalışmıyor.
Hogan

@Hogan, giriş parametresini işlemek için önerimi değiştirdim. Yine de çoğunlukla test edilmemiştir.
nvogel

@dportas - A, inID 500 ile çağrıldı, B, 50 inID ile çağrıldı - eylem - A, 51 ile döner, B 52 ile döner. Gereksinim başarısız.
Hogan

İlginç. Farklı sonuçlar alıyorum (2008r2'de). DDL ile tam reproyu gönderebilir ve derlemenizi / sürümünüzü bildirebilir misiniz?
nvogel
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.