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

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

  1. SET @maxIdentityValue = (SELECT MAX(id) FROM tablename)
  2. бежать DBCC CHECKIDENT('tablename', RESEED, @maxIdentityValue)

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

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

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

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

Пока я не использую максимальное значение. Это хранимая процедура, которую я использую (я генерирую ее с помощью запроса на sys.columns а затем просто вырезать и вставить каждый в новое окно запроса. Более грязный, медленный, менее элегантный, но я не очень знаком с хранимыми процедурами и не хочу использовать динамические запросы 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) и все остальное), так зачем вообще беспокоиться?:)

(Я публикую свой ответ с этой другой 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 (''?'')'

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

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

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

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

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

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

Другие вопросы по тегам