テーブルを使用して最後のシーケンス番号を保存する方法を次に示します。ストアド プロシージャは非常に単純です。そこにあるもののほとんどは、私が怠け者で、何かを忘れた場合の驚きが好きではないためです...ここにあります:
----- シーケンス値テーブルを作成します。
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[SequenceTbl]
(
[CurrentValue] [bigint]
) ON [PRIMARY]
GO
-----------------ストアド プロシージャの作成
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE procedure [dbo].[sp_NextInSequence](@SkipCount BigInt = 1)
AS
BEGIN
BEGIN TRANSACTION
DECLARE @NextInSequence BigInt;
IF NOT EXISTS
(
SELECT
CurrentValue
FROM
SequenceTbl
)
INSERT INTO SequenceTbl (CurrentValue) VALUES (0);
SELECT TOP 1
@NextInSequence = ISNULL(CurrentValue, 0) + 1
FROM
SequenceTbl WITH (HoldLock);
UPDATE SequenceTbl WITH (UPDLOCK)
SET CurrentValue = @NextInSequence + (@SkipCount - 1);
COMMIT TRANSACTION
RETURN @NextInSequence
END;
GO
--------Sql Manager のストアド プロシージャを使用して、テスト値を取得します。
declare @NextInSequence BigInt
exec @NextInSequence = sp_NextInSequence;
--exec @NextInSequence = sp_NextInSequence <skipcount>;
select NextInSequence = @NextInSequence;
-----現在のテーブル値を表示します。
select * from SequenceTbl;
賢明な人は、ストアド プロシージャのパラメーター (オプション) があることに気付くでしょう。これは、呼び出し元が一意の ID を必要とする複数のレコードを持っている場合に、呼び出し元が ID のブロックを予約できるようにするためです。テーブルの作成時にレコードを挿入することを覚えていれば、「IF EXISTS...INSERT INTO...」ブロック全体を削除できます。そのレコードに値 (シード値 - ID として使用されることのない数値) を挿入することも忘れない場合は、select の ISNULL(...) 部分を削除して、CurrentValue + 1 を使用することもできます。誰かがコメントする前に、私はデータベース管理者ではなくソフトウェア エンジニアであることに注意してください。だから、どんな建設的な"Top 1"、"With (HoldLock)"、"With (UPDLock)" の使用に関する批判は大歓迎です。これがどれだけうまくいくかはわかりませんが、これまでのところうまくいきます...