Сброс начального значения идентификатора после удаления записей в SQL Server
я вставил записи в таблицу базы данных SQL Server. В таблице был определен первичный ключ, и начальное значение идентификатора автоматического приращения установлено в "Yes". Это делается в первую очередь потому, что в SQL Azure каждая таблица должна иметь первичный ключ и идентификатор.
но поскольку мне нужно удалить некоторые записи из таблицы, семя идентификатора для этих таблиц будет нарушено, и столбец индекса (который автоматически генерируется с шагом 1) получит нарушенный.
как я могу сбросить столбец идентификаторов после удаления записей, чтобы столбец имел последовательность в порядке возрастания цифр?
столбец идентификаторов нигде в базе данных не используется в качестве внешнего ключа.
18 ответов:
The
DBCC CHECKIDENT
команда управления используется для сброса счетчика личности. Синтаксис команды:DBCC CHECKIDENT (table_name [, { NORESEED | { RESEED [, new_reseed_value ]}}]) [ WITH NO_INFOMSGS ]
пример:
DBCC CHECKIDENT ('[TestTable]', RESEED, 0); GO
он не поддерживался в предыдущих версиях базы данных SQL Azure, но поддерживается сейчас.
обратите внимание:
new_reseed_value
аргумент варьируется в разных версиях SQL Server согласно документации:, я нахожу эту информацию вводящей в заблуждение (просто неправильно на самом деле), потому что наблюдаемое поведение указывает, что по крайней мере SQL Server 2012 по-прежнему использует значение new_reseed_value + логика текущего значения приращения. Microsoft даже противоречит свой собственныйесли строки присутствуют в таблице, следующая строка вставляется с значение new_reseed_value значение. В версии SQL Server 2008 R2 и более ранних версий следующая вставленная строка использует значение new_reseed_value + текущее значение приращения.
Example C
найдено на той же странице:C. принуждение текущего значения идентификатора к новому значению
в следующем примере используется текущее значение идентификатора в поле Столбец AddressTypeID в таблице AddressType имеет значение 10. Поскольку таблица имеет существующие строки, следующая вставленная строка будет использовать 11 как значение, то есть, новое текущее значение, определенное для значение столбца плюс 1.
USE AdventureWorks2012; GO DBCC CHECKIDENT ('Person.AddressType', RESEED, 10); GO
тем не менее, это все оставляет параметр для другого поведения в более новых версиях SQL Server. Я думаю, единственный способ быть уверенным, пока Microsoft навести порядок в своей документации, чтобы сделать фактические испытания перед использованием.
следует отметить, что если все данные удаляются из таблицы через
DELETE
(т. е.WHERE
предложение), то до тех пор, пока a) разрешения позволяют это, и b) нет ссылок FKs на таблицу (что, по-видимому, имеет место здесь), используяTRUNCATE TABLE
было бы предпочтительнее, как это делает более эффективнымDELETE
и сбросIDENTITY
семя в то же время. Следующие сведения взяты со страницы MSDN для усечь Таблица:по сравнению с оператором DELETE, усечение таблицы имеет следующие преимущества:
используется меньше места в журнале транзакций.
оператор DELETE удаляет строки по одной и записывает запись в журнал транзакций для каждой удаленной строки. Усечение таблицы удаляет данные путем освобождения страниц данных, используемых для хранения данных таблицы и записывает только освобождение страниц в транзакции бревно.
обычно используется меньше замков.
когда оператор DELETE выполняется с помощью блокировки строк, каждая строка в таблице блокируется для удаления. Усечение таблицы всегда блокирует таблицу (включая блокировку схемы (SCH-M)) и страницу, но не каждую строку.
без исключения в таблице остаются нулевые страницы.
после выполнения инструкции DELETE таблица все еще может содержать пустые страницы. Для например, пустые страницы в куче не могут быть освобождены без по крайней мере монопольной блокировки таблицы (LCK_M_X). Если операция удаления не использует блокировку таблицы, таблица (куча) будет содержать много пустых страниц. Для индексов операция удаления может оставить пустые страницы, хотя эти страницы будут быстро освобождены в процессе фоновой очистки.
если таблица содержит столбец идентификаторов, счетчик этого столбца сбрасывается до начального значения, определенного для столбец. Если начальное значение не определено, используется значение по умолчанию 1. Чтобы сохранить счетчик идентификаторов, используйте команду Удалить.
так:
DELETE FROM [MyTable]; DBCC CHECKIDENT ('[MyTable]', RESEED, 0);
будет просто:
TRUNCATE TABLE [MyTable];
смотрите
TRUNCATE TABLE
документации (ссылка выше) для получения дополнительной информации об ограничениях и т. д.
пробовал
@anil shahs
ответ, и это сбросить личность. Но когда была вставлена новая строка, она получилаidentity = 2
. Так что вместо этого я изменил синтаксис:DELETE FROM [TestTable] DBCC CHECKIDENT ('[TestTable]', RESEED, 0) GO
тогда первая строка получит идентификатор = 1.
хотя большинство ответов предлагают переустановить на 0, но много раз нам нужно просто переустановить на следующий доступный идентификатор
declare @max int select @max=max([Id])from [TestTable] if @max IS NULL //check when max is returned as null SET @max = 0 DBCC CHECKIDENT ('[TestTable]', RESEED,@max)
это проверит таблицу и сбросит к следующему идентификатору.
хотя большинство ответов предложив
RESEED
to0
, и в то время как некоторые видят в этом недостаток дляTRUNCATED
таблицы, Microsoft имеет решение, которое исключаетID
DBCC CHECKIDENT ('[TestTable]', RESEED)
это проверит таблицу и сбросит к следующему
ID
. Это было доступно с MS SQL 2005 до настоящего времени.
чтобы явно указать значение для столбца идентификаторов
- первый поворот на identity insert -
SET Identity_Insert tblPerson ON
- в запросе insert укажите список столбцов
Insert into tblPerson(PersonId, Name) values(2, 'John')
после этого пробелы в столбце identity заполняются, и если вы хотите, чтобы SQL server вычислял значение, отключите Identity_Insert.
SET Identity_Insert tblPerson OFF
=============================
если вы удалили все строки в таблице, и вы хотите сбросить значение столбца идентификаторов.
используйте команду DBCC CHECKIDENT.
DBCC CHECKIDENT(tblPerson, RESEED, 0)
эта команда сбросит столбец PersonId identity.
@jacob
DBCC CHECKIDENT ('[TestTable]', RESEED,0) DBCC CHECKIDENT ('[TestTable]', RESEED)
работала на меня, я просто должен был очистить все записи из таблицы, а затем добавил выше в триггерную после удаления. Теперь всякий раз, когда я удаляю запись, она берется оттуда.
Это общий вопрос, и ответ всегда один: не делай этого. Значения идентичности должны рассматриваться как произвольные и, как таковые, не существует "правильного" порядка.
выдача команды 2 может сделать трюк
DBCC CHECKIDENT ('[TestTable]', RESEED,0) DBCC CHECKIDENT ('[TestTable]', RESEED)
первый сбросит идентификатор до нуля , а следующий установит его на следующее доступное значение -- Джейкоб
таблица усечения предпочтительна, поскольку она очищает записи, сбрасывает счетчик и освобождает пространство dis.
Delete и CheckIdent должны использоваться только там, где внешние ключи препятствуют усечению
сброс столбца идентификаторов с новым идентификатором...
DECLARE @MAX INT SELECT @MAX=ISNULL(MAX(Id),0) FROM [TestTable] DBCC CHECKIDENT ('[TestTable]', RESEED,@MAX)
запустите этот скрипт, чтобы сбросить столбец Identity. Вам нужно будет сделать два изменения. Замените tableXYZ на любую таблицу, которую вам нужно обновить. Кроме того, имя столбца идентификаторов должно быть удалено из временной таблицы. Это было мгновенно на таблице с 35 000 строк и 3 столбцов. Очевидно, создайте резервную копию таблицы и сначала попробуйте это в тестовой среде.
select * into #temp From tableXYZ set identity_insert tableXYZ ON truncate table tableXYZ alter table #temp drop column (nameOfIdentityColumn) set identity_insert tableXYZ OFF insert into tableXYZ select * from #temp
использовать эту хранимую процедуру:
IF (object_id('[dbo].[pResetIdentityField]') IS NULL) BEGIN EXEC('CREATE PROCEDURE [dbo].[pResetIdentityField] AS SELECT 1 FROM DUMMY'); END GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[pResetIdentityField] @pSchemaName NVARCHAR(1000) , @pTableName NVARCHAR(1000) AS DECLARE @max INT; DECLARE @fullTableName NVARCHAR(2000) = @pSchemaName + '.' + @pTableName; DECLARE @identityColumn NVARCHAR(1000); SELECT @identityColumn = c.[name] FROM sys.tables t INNER JOIN sys.schemas s ON t.[schema_id] = s.[schema_id] INNER JOIN sys.columns c ON c.[object_id] = t.[object_id] WHERE c.is_identity = 1 AND t.name = @pTableName AND s.[name] = @pSchemaName IF @identityColumn IS NULL BEGIN RAISERROR( 'One of the following is true: 1. the table you specified doesn''t have an identity field, 2. you specified an invalid schema, 3. you specified an invalid table' , 16 , 1); RETURN; END; DECLARE @sqlString NVARCHAR(MAX) = N'SELECT @maxOut = max(' + @identityColumn + ') FROM ' + @fullTableName; EXECUTE sp_executesql @stmt = @sqlString, @params = N'@maxOut int OUTPUT', @maxOut = @max OUTPUT IF @max IS NULL SET @max = 0 print(@max) DBCC CHECKIDENT (@fullTableName, RESEED, @max) go --exec pResetIdentityField 'dbo', 'Table'
просто пересматриваю свой ответ. Я наткнулся на странное поведение в sql server 2008 r2, о котором вы должны знать.
drop table test01 create table test01 (Id int identity(1,1), descr nvarchar(10)) execute pResetIdentityField 'dbo', 'test01' insert into test01 (descr) values('Item 1') select * from test01 delete from test01 execute pResetIdentityField 'dbo', 'test01' insert into test01 (descr) values('Item 1') select * from test01
первый выбор производит
0, Item 1
.второй производит
1, Item 1
. Если вы выполняете сброс сразу после создания таблицы, следующее значение равно 0. Честно говоря, я не удивлен, что Microsoft не может получить этот материал правильно. Я обнаружил это, потому что у меня есть файл сценария, который заполняет справочные таблицы, которые я иногда запускаю после повторного создания таблиц, а иногда и когда таблицы уже созданы.
DBCC CHECKIDENT (<TableName>, reseed, 0)
это установит текущее значение идентификатора в 0.
при вставке следующего значения значение идентификатора увеличивается до 1.
для полного удаления строк и сброса количества идентификаторов я использую это (SQL Server 2008 R2)
USE mydb -- ################################################################################################################## -- DANGEROUS!!!! USE WITH CARE -- ################################################################################################################## DECLARE db_cursor CURSOR FOR SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_CATALOG = 'mydb' DECLARE @tblname VARCHAR(50) SET @tblname = '' OPEN db_cursor FETCH NEXT FROM db_cursor INTO @tblname WHILE @@FETCH_STATUS = 0 BEGIN IF CHARINDEX('mycommonwordforalltablesIwanttodothisto', @tblname) > 0 BEGIN EXEC('DELETE FROM ' + @tblname) DBCC CHECKIDENT (@tblname, RESEED, 0) END FETCH NEXT FROM db_cursor INTO @tblname END CLOSE db_cursor DEALLOCATE db_cursor GO
его всегда лучше использовать усечь когда это возможно вместо удаления всех записей, поскольку он также не использует пространство журнала.
в случае, если нам нужно удалить и нужно сбросить семя, всегда помните, что если таблица никогда не была заполнена, и вы использовали
DBCC CHECKIDENT('tablenem',RESEED,0)
тогда первая запись будет тож = 0 как указано на Примечаниев вашем случае только перестроить индекс и не беспокойтесь о потере серия идентичность как это общий сценарий.