キーテーブルを使用して、2番目のID列の増分部分を格納できます。このソリューションは、クライアント側のコードに依存せず、自動的に複数年認識されます。とき@DateAdded
のパラメータは、以前に使用されていない年に渡し、それが自動的に値の新しいセットを使用して開始されID2
、その年に基づいて、コラム。その結果、procが前の年の行を挿入するために使用される場合、それらの行は、増分の「正しい」値で挿入されます。GetNextID()
PROCを更新しようとしたときに5つのシーケンシャルデッドロックが発生した場合にのみ、呼び出し元にエラーを渡して、優雅にデッドロックの可能性を処理するために適していtblIDs
テーブルを。
使用する新しい値を返すストアドプロシージャと共に、現在使用されているID値を含む年に1行を格納するテーブルを作成します。
CREATE TABLE [dbo].[tblIDs]
(
IDName nvarchar(255) NOT NULL,
LastID int NULL,
CONSTRAINT [PK_tblIDs] PRIMARY KEY CLUSTERED
(
[IDName] ASC
) WITH
(
PAD_INDEX = OFF
, STATISTICS_NORECOMPUTE = OFF
, IGNORE_DUP_KEY = OFF
, ALLOW_ROW_LOCKS = ON
, ALLOW_PAGE_LOCKS = ON
, FILLFACTOR = 100
)
);
GO
CREATE PROCEDURE [dbo].[GetNextID](
@IDName nvarchar(255)
)
AS
BEGIN
/*
Description: Increments and returns the LastID value from
tblIDs for a given IDName
Author: Max Vernon / Mike Defehr
Date: 2012-07-19
*/
SET NOCOUNT ON;
DECLARE @Retry int;
DECLARE @EN int, @ES int, @ET int;
SET @Retry = 5;
DECLARE @NewID int;
WHILE @Retry > 0
BEGIN
SET @NewID = NULL;
BEGIN TRY
UPDATE dbo.tblIDs
SET @NewID = LastID = LastID + 1
WHERE IDName = @IDName;
IF @NewID IS NULL
BEGIN
SET @NewID = 1;
INSERT INTO tblIDs (IDName, LastID)
VALUES (@IDName, @NewID);
END
SET @Retry = -2; /* no need to retry since the
operation completed */
END TRY
BEGIN CATCH
IF (ERROR_NUMBER() = 1205) /* DEADLOCK */
SET @Retry = @Retry - 1;
ELSE
BEGIN
SET @Retry = -1;
SET @EN = ERROR_NUMBER();
SET @ES = ERROR_SEVERITY();
SET @ET = ERROR_STATE()
RAISERROR (@EN,@ES,@ET);
END
END CATCH
END
IF @Retry = 0 /* must have deadlock'd 5 times. */
BEGIN
SET @EN = 1205;
SET @ES = 13;
SET @ET = 1
RAISERROR (@EN,@ES,@ET);
END
ELSE
SELECT @NewID AS NewID;
END
GO
テーブルとそれに行を挿入するためのプロシージャ:
CREATE TABLE dbo.Cond
(
CondID INT NOT NULL
CONSTRAINT PK_Cond
PRIMARY KEY CLUSTERED
IDENTITY(1,1)
, CondID2 VARCHAR(30) NOT NULL
, Date_Added DATE NOT NULL
);
GO
CREATE PROCEDURE dbo.InsertCond
(
@DateAdded DATE
)
AS
BEGIN
DECLARE @NextID INT;
DECLARE @Year INT;
DECLARE @IDName NVARCHAR(255);
SET @Year = DATEPART(YEAR, @DateAdded);
DECLARE @Res TABLE
(
NextID INT NOT NULL
);
SET @IDName = 'Cond_' + CONVERT(VARCHAR(30), @Year, 0);
INSERT INTO @Res (NextID)
EXEC dbo.GetNextID @IDName;
INSERT INTO dbo.Cond (CondID2, Date_Added)
SELECT CONVERT(VARCHAR(30), NextID) + '/' +
SUBSTRING(CONVERT(VARCHAR(30), @Year), 3, 2), @DateAdded
FROM @Res;
END
GO
いくつかのサンプルデータを挿入します。
EXEC dbo.InsertCond @DateAdded = '2015-12-30';
EXEC dbo.InsertCond @DateAdded = '2015-12-31';
EXEC dbo.InsertCond @DateAdded = '2016-01-01';
EXEC dbo.InsertCond @DateAdded = '2016-01-02';
両方のテーブルを表示:
SELECT *
FROM dbo.Cond;
SELECT *
FROM dbo.tblIDs;
結果:
キーテーブルとストアドプロシージャは、この質問に由来します。