Сброс начального значения идентификатора после удаления записей в SQL Server


я вставил записи в таблицу базы данных SQL Server. В таблице был определен первичный ключ, и начальное значение идентификатора автоматического приращения установлено в "Yes". Это делается в первую очередь потому, что в SQL Azure каждая таблица должна иметь первичный ключ и идентификатор.

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

как я могу сбросить столбец идентификаторов после удаления записей, чтобы столбец имел последовательность в порядке возрастания цифр?

столбец идентификаторов нигде в базе данных не используется в качестве внешнего ключа.

18 512

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 согласно документации:

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

  • обычно используется меньше замков.

    когда оператор 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 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 укажите список столбцов 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 как указано на Примечание

в вашем случае только перестроить индекс и не беспокойтесь о потере серия идентичность как это общий сценарий.

Во-Первых: Спецификация Идентичности Просто : "Нет" > > Сохранить Базу Данных Выполнить Проект

после этого: спецификация идентичности просто : "да" > > сохранить базу данных выполнить проект

Ваш идентификатор базы данных, PK начать с 1 >>