Сброс автоинкремента в SQL Server после удаления


266

Я удалил некоторые записи из таблицы в базе данных SQL Server. Теперь идентификатор изменяется с 101 на 1200. Я хочу снова удалить записи, но хочу, чтобы идентификаторы вернулись к 102. Есть ли способ сделать это в SQL Server?


46
Пожалуйста, не говорите «Не делай этого». Я ненавижу, когда я спрашиваю, как сделать что-то, и все, что я получаю, не делает. Да, сброс идентификатора может вызвать проблемы с внешним ключом, но только если вы не знаете свою базу данных и программу соответственно. Есть очень веские причины для сброса личности после запланированного удаления - они называются аудиторами. Аудиторы ненавидят видеть пробелы, поэтому заполняйте их, делайте это контролируемым образом и следите за соблюдением внешних ключей.

6
@spyder, знаете ли вы, что у вас будут пробелы, если откат вставки будет выполнен не только для удаления? Вы не можете избежать пробелов с автоинкрементом, и глупо пытаться. Я работал в аудиторском агентстве, и компетентные аудиторы могут объяснить им это. Кроме того, если у вас есть соответствующие таблицы аудита, они могут увидеть, что случилось с этими записями. Или, если по юридическим причинам не должно быть никаких пробелов (есть несколько случаев этого), то только некомпетентный разработчик будет использовать автоинкремент, и аудиторы справедливо расстроены.
HLGEM

Ответы:


457

Выполните следующую команду для повторного заполнения mytable, чтобы начать с 1:

DBCC CHECKIDENT (mytable, RESEED, 0)

Об этом читайте в Книгах онлайн (BOL, справка по SQL). Также будьте осторожны, чтобы у вас не было записей выше, чем семена, которые вы устанавливаете.


4
... потому что идентификаторы этих записей будут снова использованы снова, что приведет к плохому беспорядку.
2010 г.

3
На самом деле, чтобы начать идентификаторы с 1, вам нужно использовать 0: DBCC CHECKIDENT (mytable, RESEED, 0)
Райан Ланди

7
«DBCC CHECKIDENT (имя_таблицы)» устанавливает начальное значение для идентификатора с самым высоким идентификатором в таблице, чем вам не нужно быть «осторожным»
user1027167

4
@ user1027167 Нет, твой ответ не сработал для меня. Он продолжал увеличиваться на самом высоком идентификаторе, который был сохранен внутри. Мне пришлось явно использовать «RESEED, 18» в моем случае, чтобы получить «19» в качестве следующего идентификатора. Без этого радостно продолжал увеличиваться на «29».
Маттис Кохли

DBCC CHECKIDENT (имя_таблицы) изменяет начальное значение только в том случае, если значение идентификатора меньше максимального значения в столбце. Поэтому, если значение идентификатора уже больше, чем в случае @MatthisKohli, необходимо вызвать явное повторное заполнение.
Мартин

82
DBCC CHECKIDENT('databasename.dbo.tablename', RESEED, number)

если число = 0, то при следующей вставке поле автоинкремента будет содержать значение 1

если число = 101, то при следующей вставке поле автоинкремента будет содержать значение 102


Некоторая дополнительная информация ... Может быть полезна для вас

Перед тем, как задать автоинкремент numberв вышеприведенном запросе, вы должны убедиться, что столбец автоинкрементации в вашей существующей таблице содержит значения меньше этого number.

Чтобы получить максимальное значение столбца (column_name) из таблицы (table1), вы можете использовать следующий запрос

 SELECT MAX(column_name) FROM table1

37

полу идиот-доказательство:

declare @max int;  
select @max = max(key) from table;  
dbcc checkident(table,reseed,@max)

http://sqlserverplanet.com/tsql/using-dbcc-checkident-to-reseed-a-table-after-delete


1
"DBCC CHECKIDENT (table_name)" делает то же самое (возможно без условий гонки)
user1027167

2
@ user1027167 В документах говорится «если текущее значение идентификатора для таблицы меньше максимального значения идентификатора, хранящегося в столбце идентификаторов»; это не покрывает очистку после удаления данных (повторное использование идентификаторов - часто плохая идея). Проверено на SQL 2008
user423430

1
Лучший систематический и автоматический ответ. Браво!
Мехди Хадемлу


6

Удалить и восстановить все таблицы в базе данных.

    USE [DatabaseName]
    EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"       -- Disable All the constraints
    EXEC sp_MSForEachTable "DELETE FROM ?"    -- Delete All the Table data
    Exec sp_MSforeachtable 'DBCC CHECKIDENT(''?'', RESEED, 0)' -- Reseed All the table to 0
    Exec sp_msforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"  -- Enable All  the constraints back

-- You may ignore the errors that shows the table without Auto increment field.


4

На основании принятого ответа для тех, кто столкнулся с подобной проблемой, с полной квалификацией схемы:

( [MyDataBase].[MySchemaName].[MyTable]) ... приводит к ошибке, вы должны быть в контексте этой БД

То есть следующее выдаст ошибку:

DBCC CHECKIDENT ([MyDataBase].[MySchemaName].[MyTable], RESEED, 0)

Вместо этого заключите полное имя таблицы в одинарные кавычки:

DBCC CHECKIDENT ('[MyDataBase].[MySchemaName].[MyTable]', RESEED, 0)

4

Несколько ответов рекомендуют использовать утверждение примерно так:

DBCC CHECKIDENT (mytable, RESEED, 0)

Но ОП сказал «удалил некоторые записи», что может быть не все из них, поэтому значение 0 не всегда является правильным. В другом ответе предлагалось автоматически найти максимальное текущее значение и пересчитать его, но это приведет к проблемам, если в таблице нет записей, и, следовательно, max () вернет NULL. Комментарий предложил использовать просто

DBCC CHECKIDENT (mytable)

сбросить значение, но другой комментарий правильно заявил, что это только увеличивает значение до максимума уже в таблице; это не уменьшит значение, если оно уже выше максимального значения в таблице, что и хотел сделать ОП.

Лучшее решение объединяет эти идеи. Первый CHECKIDENT сбрасывает значение до 0, а второй сбрасывает его до самого высокого значения в настоящее время в таблице, если в таблице есть записи:

DBCC CHECKIDENT (mytable, RESEED, 0)
DBCC CHECKIDENT (mytable)

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


4

Я хочу добавить этот ответ, потому что DBCC CHECKIDENT-approach создаст проблемы с продуктом при использовании схем для таблиц. Используйте это, чтобы быть уверенным:

DECLARE @Table AS NVARCHAR(500) = 'myschema.mytable';
DBCC CHECKIDENT (@Table, RESEED, 0);

Если вы хотите проверить успешность операции, используйте

SELECT IDENT_CURRENT(@Table);

который должен выводиться 0в примере выше.


1

Вы не хотите делать это в целом. Reseed может создать проблемы с целостностью данных. Это действительно только для использования в системах разработки, где вы стираете все тестовые данные и начинаете заново. Его не следует использовать в производственной системе, если все связанные записи не были удалены (не каждая таблица, которая должна быть связана с внешним ключом!). Делая это, вы можете создать беспорядок, особенно если вы хотите делать это регулярно после каждого удаления. Не стоит беспокоиться о пробелах в значениях полей идентичности.


6
Я не буду использовать это все время, и это было только на тестовой БД.
Jumbojs

0

Как насчет этого?

ALTER TABLE `table_name`
  MODIFY `id` int(12) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=0;

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

Вы также можете написать это так, чтобы сделать это однострочным решением:

ALTER TABLE `table_name` MODIFY `id` int(12) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=0;

1
Спасибо за этот фрагмент кода, который может предоставить некоторую ограниченную, немедленную помощь. Надлежащее объяснение было бы значительно улучшить свою долгосрочную ценность , показывая , почему это хорошее решение проблемы, и сделает его более полезным для читателей будущих с другими подобными вопросами. Пожалуйста, измените свой ответ, чтобы добавить некоторые объяснения, в том числе предположения, которые вы сделали.
До свидания StackExchange
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.