Подтвердить что ты не робот

Расширение идентификатора столбца SQL Server 2012, переходящее с 6 до 1000+ на 7-ю запись

У меня странный сценарий, в котором столбец auto identity int в моей базе данных SQL Server 2012 не увеличивается правильно.

Скажем, у меня есть таблица, которая использует идентификатор int auto в качестве первичного ключа, который периодически изменяется при пропуске, например:

1, 2, 3, 4, 5, 1004, 1005

Это происходит на случайном числе таблиц в очень случайное время, не может реплицировать его, чтобы найти какие-либо тенденции.

Как это происходит? Есть ли способ остановить его?

4b9b3361

Ответ 1

Это все нормально. Microsoft добавила sequences в SQL Server 2012, наконец, я могу добавить и изменить способ создания ключей идентификации. Посмотрите здесь для объяснения.

Если вы хотите иметь старое поведение, вы можете:

  • использовать флаг трассировки 272 - это приведет к созданию записи журнала для каждого сгенерированного значения идентификации. На производительность генерации идентификаторов может повлиять включение этого символа трассировки.
  • используйте генератор последовательности с настройкой NO CACHE (http://msdn.microsoft.com/en-us/library/ff878091.aspx)

Ответ 2

Я знаю, что мой ответ может опоздать на вечеринку. Но я решил по-другому, добавив начальную хранимую процедуру в SQL Server 2012.

Создайте следующую хранимую процедуру в основной БД.

USE [master]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[ResetOrderIdentityAfterRestart]
AS
BEGIN

begin TRAN
    declare @id int = 0
    SELECT @id =  MAX(id) FROM [DatabaseName].dbo.[TableName]
    --print @id
    DBCC CHECKIDENT ('[DatabaseName].dbo.[TableName]', reseed, @id)
Commit

END

Затем добавьте его в Пуск, используя следующий синтаксис.

EXEC sp_procoption 'ResetOrderIdentityAfterRestart', 'startup', 'on';

Это хорошая идея, если у вас мало таблиц. но если вам нужно сделать это для многих таблиц, этот метод по-прежнему работает, но не очень хорошая идея.

Ответ 4

В то время как флаг 272 трассировки может работать для многих, он определенно не будет работать для размещенных установок Sql Server Express. Итак, я создал таблицу идентификации и использую ее с помощью триггера INSTEAD OF. Я надеюсь, что это поможет кому-то другому и/или даст другим возможность улучшить мое решение. Последняя строка позволяет вернуть последний столбец идентификатора. Поскольку я обычно использую это, чтобы добавить одну строку, это работает, чтобы вернуть личность одной вставленной строки.

Таблица идентичности:

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