SQLServer2012データベースのautoidentityint列が正しくインクリメントされないという奇妙なシナリオがあります。
主キーとしてint自動IDを使用するテーブルがあり、それが散発的に増分をスキップしているとします。次に例を示します。
1、2、3、4、5、1004、1005
これは非常にランダムな時間にランダムな数のテーブルで発生しており、傾向を見つけるためにそれを複製することはできません。
これはどのように起こっていますか?それを止める方法はありますか?
SQLServer2012データベースのautoidentityint列が正しくインクリメントされないという奇妙なシナリオがあります。
主キーとしてint自動IDを使用するテーブルがあり、それが散発的に増分をスキップしているとします。次に例を示します。
1、2、3、4、5、1004、1005
これは非常にランダムな時間にランダムな数のテーブルで発生しており、傾向を見つけるためにそれを複製することはできません。
これはどのように起こっていますか?それを止める方法はありますか?
これはすべて完全に正常です。Microsoftsequences
は SQL Server 2012 に追加しました。最終的に、ID キーの生成方法を追加および変更する可能性があります。いくつかの説明については、こちらをご覧ください。
古い動作をしたい場合は、次のことができます。
同じ問題が発生し、SQL Server 2012 で次のバグ レポートが見つかりました。それでも問題が発生する条件を参照してください。いくつかの回避策があります (ただし、試していません)。 フェールオーバーまたは再起動により ID が再シードされる
トレース フラグ 272 は多くの場合に機能する可能性がありますが、ホストされた Sql Server Express インストールでは確実に機能しません。そこで、ID テーブルを作成し、これを INSTEAD OF トリガーで使用します。これが他の誰かに役立つこと、および/または他の人に私のソリューションを改善する機会を与えることを願っています。最後の行では、最後に追加された ID 列を返すことができます。通常、これを使用して単一の行を追加するため、これは挿入された単一の行の ID を返すために機能します。
ID テーブル:
CREATE TABLE [dbo].[tblsysIdentities](
[intTableId] [int] NOT NULL,
[intIdentityLast] [int] NOT NULL,
[strTable] [varchar](100) NOT NULL,
[tsConcurrency] [timestamp] NULL,
CONSTRAINT [PK_tblsysIdentities] PRIMARY KEY CLUSTERED
(
[intTableId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
そして挿入トリガー:
-- INSERT --
IF OBJECT_ID ('dbo.trgtblsysTrackerMessagesIdentity', 'TR') IS NOT NULL
DROP TRIGGER dbo.trgtblsysTrackerMessagesIdentity;
GO
CREATE TRIGGER trgtblsysTrackerMessagesIdentity
ON dbo.tblsysTrackerMessages
INSTEAD OF INSERT AS
BEGIN
DECLARE @intTrackerMessageId INT
DECLARE @intRowCount INT
SET @intRowCount = (SELECT COUNT(*) FROM INSERTED)
SET @intTrackerMessageId = (SELECT intIdentityLast FROM tblsysIdentities WHERE intTableId=1)
UPDATE tblsysIdentities SET intIdentityLast = @intTrackerMessageId + @intRowCount WHERE intTableId=1
INSERT INTO tblsysTrackerMessages(
[intTrackerMessageId],
[intTrackerId],
[strMessage],
[intTrackerMessageTypeId],
[datCreated],
[strCreatedBy])
SELECT @intTrackerMessageId + ROW_NUMBER() OVER (ORDER BY [datCreated]) AS [intTrackerMessageId],
[intTrackerId],
[strMessage],
[intTrackerMessageTypeId],
[datCreated],
[strCreatedBy] FROM INSERTED;
SELECT TOP 1 @intTrackerMessageId + @intRowCount FROM INSERTED;
END