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

CHECKIDENT DBCC устанавливает идентификатор 0

Я использую этот код для reset идентификатора в таблице:

DBCC CHECKIDENT('TableName', RESEED, 0)

Это работает отлично в большинстве случаев, с первой вставкой, которую я вставляю 1 в столбец идентификатора. Однако, если я удаляю db и воссоздаю его (используя написанные скрипты), а затем вызываю DBCC CHECKIDENT, первый вставленный элемент будет иметь идентификатор 0.

Любые идеи?

EDIT: После исследования выяснилось, что я не читал документацию должным образом: http://msdn.microsoft.com/en-us/library/aa258817(SQL.80).aspx - "Текущее значение идентификатора устанавливается в значение new_reseed_value. Если ни одна строка не была вставлена ​​в таблицу с момента ее создания, первая строка, вставленная после выполнения DBCC CHECKIDENT, будет использовать new_reseed_value как идентификатор. В противном случае следующая вставленная строка будет использовать new_reseed_value + 1."

4b9b3361

Ответ 1

Как вы указали в своем вопросе, это документированное поведение. Мне все еще кажется странным. Я использую, чтобы повторно заполнить тестовую базу данных, и хотя я не полагаюсь на значения полей идентификации, было немного раздражающе иметь разные значения при первом заполнении базы данных с нуля и после удаления всех данных и повторного заполнения.

Возможным решением является использование truncate для очистки таблицы вместо удаления. Но тогда вам нужно отбросить все ограничения и потом их воссоздать

Таким образом, он всегда ведет себя как вновь созданная таблица, и нет необходимости вызывать DBCC CHECKIDENT. Первое значение идентификатора будет указано в определении таблицы, и оно будет одинаковым независимо от того, вставляете ли вы данные в первый раз или для N-го

Ответ 2

Вы правы в том, что вы пишете при редактировании вашего вопроса.

После запуска DBCC CHECKIDENT('TableName', RESEED, 0):
- Новые созданные таблицы начнутся с идентификатора 0
- Существующие таблицы будут продолжаться с идентификатором 1

Решение находится в script ниже, это своего рода бедный mans-truncate:)

-- Remove all records from the Table
DELETE FROM TableName

-- Use sys.identity_columns to see if there was a last known identity value
-- for the Table. If there was one, the Table is not new and needs a reset
IF EXISTS (SELECT * FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = 'TableName' AND last_value IS NOT NULL) 
    DBCC CHECKIDENT (TableName, RESEED, 0);

Ответ 3

Измените оператор на

  DBCC CHECKIDENT('TableName', RESEED, 1)

Это начнется с 2 (или 1 при воссоздании таблицы), но никогда не будет 0.

Ответ 4

Я сделал это как эксперимент с reset значением 0, так как я хочу, чтобы мой первый столбец идентичности был 0 и он работал.

dbcc CHECKIDENT(MOVIE,RESEED,0)
dbcc CHECKIDENT(MOVIE,RESEED,-1)
DBCC CHECKIDENT(MOVIE,NORESEED)

Ответ 5

Кажется смешным, что вы не можете установить/сбросить столбец идентификаторов с помощью одной команды, чтобы охватить оба случая, если в таблицу были вставлены записи. Я не мог понять поведение, которое я испытывал, пока я не наткнулся на этот вопрос на SO!

Мое решение (некрасиво, но работает) состоит в том, чтобы явно проверить таблицу sys.identity_columns.last_value (которая сообщает вам, вставлены ли в таблицу записи) и вызывать соответствующую команду DBCC CHECKIDENT в каждом случае. Это выглядит следующим образом:

DECLARE @last_value INT = CONVERT(INT, (SELECT last_value FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = 'MyTable'));
IF @last_value IS NULL
    BEGIN
        -- Table newly created and no rows inserted yet; start the IDs off from 1
        DBCC CHECKIDENT ('MyTable', RESEED, 1);
    END
ELSE
    BEGIN
        -- Table has rows; ensure the IDs continue from the last ID used
        DECLARE @lastValUsed INT = (SELECT ISNULL(MAX(ID),0) FROM MyTable);
        DBCC CHECKIDENT ('MyTable', RESEED, @lastValUsed);
    END

Ответ 7

Я использовал это в SQL для установки IDENTITY для определенного значения: -

DECLARE @ID int = 42;
DECLARE @TABLENAME  varchar(50) = 'tablename'

DECLARE @SQL nvarchar(1000) = 'IF EXISTS (SELECT * FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = '''[email protected]+''' AND last_value IS NOT NULL)
    BEGIN
        DBCC CHECKIDENT('[email protected]+', RESEED,' + CONVERT(VARCHAR(10),@ID-1)+');
    END
    ELSE
    BEGIN
        DBCC CHECKIDENT('[email protected]+', RESEED,' + CONVERT(VARCHAR(10),@ID)+');
    END';
EXEC (@SQL);

И это в С# для установки определенного значения: -

SetIdentity(context, "tablename", 42);
.
.
private static void SetIdentity(DbContext context, string table,int id)
{
    string str = "IF EXISTS (SELECT * FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = '" + table
        + "' AND last_value IS NOT NULL)\nBEGIN\n";
    str += "DBCC CHECKIDENT('" + table + "', RESEED," + (id - 1).ToString() + ");\n";
    str += "END\nELSE\nBEGIN\n";
    str += "DBCC CHECKIDENT('" + table + "', RESEED," + (id).ToString() + ");\n";
    str += "END\n";
    context.Database.ExecuteSqlCommand(str);
}

Это основывается на приведенных выше ответах и ​​всегда гарантирует, что следующее значение равно 42 (в данном случае).

Ответ 8

Просто сделайте это:

IF EXISTS (SELECT * FROM tablename)
BEGIN
    DELETE from  tablename
    DBCC checkident ('tablename', reseed, 0)
END

Ответ 9

USE AdventureWorks2012;  
GO  
DBCC CHECKIDENT ('Person.AddressType', RESEED, 0);  
GO 



AdventureWorks2012=Your databasename
Person.AddressType=Your tablename