DBCC CHECKIDENT RESEED-требуется ли новое значение?
вся документация, которую я читал о пересеве, предполагает что-то вроде:
SET @maxIdentityValue = (SELECT MAX(id) FROM tablename)
- 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, сбрасывается с помощью максимальное значение в столбце идентификаторов.