DBCC CHECKIDENT RESEED-требуется ли новое значение?

вся документация, которую я читал о пересеве, предполагает что-то вроде:

  1. SET @maxIdentityValue = (SELECT MAX(id) FROM tablename)
  2. run DBCC CHECKIDENT('tablename', RESEED, @maxIdentityValue)

и пока мне кажется, что простой DBCC CHECKIDENT('tablename', RESEED) - Это все, что нужно, и он будет автоматически определить правильное значение идентификатора из таблицы без указания максимального значения.

есть ли причина (производительность или иначе), что извлечение значения с помощью MAX первый предпочтительнее?

Piggyback вопрос: причина, по которой мне нужно переустановить, заключается в том, что я использую репликацию, и идентификаторы продолжают получать значение Null каждый раз, когда выполняется репликация базы данных. Что я делаю не так? Как я могу поддерживать правильное семя идентичности для каждой таблицы?

обновление (текущее решение)

пока я не использую максимальное значение. Это хранимая процедура, которую я использую (я генерирую ее с помощью запроса на sys.columns и потом просто вырезать и вставить друг в новое окно запроса. Messier, медленнее, менее элегантно, но я не очень хорошо знаком с хранимыми процедурами и не хочу использовать динамические SQL-запросы):

declare @seedval integer
declare @maxval integer
declare @newval integer
set @seedval = (select ident_current('mytable'));
set @maxval = (select MAX(id) from mytable);
if @maxval > @seedval or @seedval is NULL
BEGIN
    print 'Need to reseed: max is '  + cast(@maxval as varchar) + ' and seed is ' + cast(@seedval as varchar) 
    dbcc checkident('mytable', RESEED);
    set @newval = (select ident_current('mytable'));
    print 'Max is ' + cast(@maxval as varchar) + ' and seed is ' + cast(@newval as varchar) 
END 
ELSE
    print 'No need to reseed'; 

3 ответов


Как говорится в MSDN, достаточно просто использовать:

 DBCC CHECKIDENT('tablename', RESEED)  

большую часть времени, однако есть эти два условия, где он не будет работать:

  • текущее значение идентификатора больше максимального значения в таблице.
  • все строки удаляются из таблицы.

в котором вы должны пойти с тем, что вы упомянули (выберите max (id) и остальные) , так зачем беспокоиться в первом место? :)


есть случаи, когда вы можете определить max, чтобы вы могли переустановить и оставить пробел (например, max + 100). Один случай может быть, когда у вас есть несколько копий таблицы, и вы собираетесь распространять независимые, но взаимоисключающие диапазоны идентификаторов из них.

но все же я не уверен, что RESEED без параметра будет работать правильно во всех сценариях.

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

в любом случае, вы захотите обернуть MAX и переустановить транзакцию, чтобы предотвратить вероятность того, что пользователь вставит новую строку после того, как вы взяли max, но до того, как вы выпустили reseed.


(Я перепечатываю свой ответ с этой другой страницы SO)

возможно, самый простой способ (как сумасшедший, как это звучит и как код пахнет, как это выглядит)-просто запустить DBCC CHECKIDENT дважды так:

-- sets all the seeds to 1
exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT (''?'', RESEED, 1)'

-- run it again to get MSSQL to figure out the MAX/NEXT seed automatically
exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT (''?'')'

сделано.

Если вы хотите, вы можете запустить его еще раз, чтобы увидеть, что все семена были установлены в:

-- run it again to display what the seeds are now set to
exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT (''?'')'

Это просто творческий способ воспользоваться комментарием из документации:

Если тока значение идентификатора для таблицы меньше максимального значение identity, хранящееся в столбце identity, сбрасывается с помощью максимальное значение в столбце идентификаторов.