Сброс начального значения идентификатора после удаления записей в 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 согласно документации:

если строки присутствуют в таблице, следующая строка вставлено с значение new_reseed_value значение. В версии SQL Server 2008 R2 и более ранних версиях следующая вставленная строка использует значение new_reseed_value + текущее значение приращения.

, я нахожу эту информацию вводящей в заблуждение (просто неправильно на самом деле), потому что наблюдаемое поведение указывает, что по крайней мере SQL Server 2012 по-прежнему использует значение new_reseed_value + логика текущего значения приращения. Microsoft даже противоречит своя Example C найдено на той же странице:

C. принуждение текущего значения идентификатора к новому значению

следующий пример заставляет текущее значение идентификатора в Столбец AddressTypeID в таблице AddressType имеет значение 10. Поскольку таблица имеет существующие строки, следующая вставленная строка будет использовать 11 как значение, то есть, новое текущее значение, определенное для значение столбца плюс 1.

USE AdventureWorks2012;  
GO  
DBCC CHECKIDENT ('Person.AddressType', RESEED, 10);  
GO

тем не менее, это все оставляет вариант для другого поведения в новых версиях SQL Server. Я думаю, единственный способ убедиться, пока Microsoft не прояснит вещи в своей собственной документации, - это сделать фактические тесты перед использованием.


DBCC CHECKIDENT ('TestTable', RESEED, 0)
GO

где 0 identity пуск стоимостью


следует отметить, что если все данные удаляются из таблицы через 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 до текущего.

https://msdn.microsoft.com/en-us/library/ms176057.aspx


чтобы явно указать значение для столбца идентификаторов

  1. сначала включите identity insert -SET Identity_Insert tblPerson ON
  2. в запросе 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 >>