Сброс начального значения идентификатора после удаления записей в SQL Server
я вставил записи в таблицу базы данных SQL Server. В таблице был определен первичный ключ, а семя идентификатора автоматического приращения установлено в "Да". Это делается главным образом потому, что в SQL Azure каждая таблица должна иметь первичный ключ и идентификатор.
но так как я должен удалить некоторые записи из таблицы, семя идентификатора для этих таблиц будет нарушено, и столбец индекса (который автоматически генерируется с шагом 1) получит нарушенный.
как я могу сбросить столбец идентификаторов после удаления записей, чтобы столбец имел последовательность в порядке возрастания?
столбец identity не используется в качестве внешнего ключа нигде в базе данных.
18 ответов
на 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 удаляет строки по одной и записывает запись в журнал транзакций для каждой удаленной строки. TRUNCATE TABLE удаляет данные путем освобождения страниц данных, используемых для хранения данных таблицы, и записывает только освобождение страниц в транзакции бревно.
обычно используется меньше блокировок.
когда инструкция DELETE выполняется с помощью блокировки строк, каждая строка в таблице блокируется для удаления. Усеченная таблица всегда блокирует таблицу (включая блокировку схемы (SCH-M)) и страницу, но не каждую строку.
без исключения в таблице остаются нулевые страницы.
после выполнения инструкции DELETE таблица все еще может содержать пустые страницы. Для например, пустые страницы в куче не могут быть освобождены без блокировки таблицы exclusive (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
тогда первая строка получит identity = 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)
это проверит таблицу и сбросит к следующему ID.
хотя большинство ответов предложив RESEED
to 0
, и пока некоторые видят это как недостаток для TRUNCATED
таблицы, Microsoft имеет решение, которое исключает ID
DBCC CHECKIDENT ('[TestTable]', RESEED)
это проверит таблицу и сбросит к следующему ID
. Это было доступно с MS SQL 2005 до текущего.
чтобы явно указать значение для столбца идентификаторов
- сначала включите identity insert -
SET Identity_Insert tblPerson ON
- в запросе insert укажите столбец list
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.
@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)
тогда первая запись получит identity = 0
как указано на документация msdn
в вашем случае только перестроить индекс и не беспокойтесь о потере серия идентичность как это распространенный сценарий.
Во-Первых: Спецификация Идентичности Просто : "Нет" > > Сохранить Базу Данных Выполнить Проект
после этого: спецификация идентичности просто : "да" > > сохранить базу данных выполнить проект
Ваш идентификатор базы данных, PK начать с 1 >>