Reset идентификационное семя после удаления записей в SQL Server

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

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

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

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

Ответ 1

Команда DBCC CHECKIDENT используется для reset идентификатора. Синтаксис команды:

DBCC CHECKIDENT (table_name [, { NORESEED | { RESEED [, new_reseed_value ]}}])
[ WITH NO_INFOMSGS ]

Пример:

DBCC CHECKIDENT ('[TestTable]', RESEED, 0);
GO

Он не поддерживался в предыдущих версиях базы данных Azure SQL, но теперь поддерживается.


Обратите внимание, что аргумент new_reseed_value варьируется в версиях SQL Server в соответствии с документацией:

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

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

С. Принуждение текущего значения идентичности к новому значению

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

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

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

Ответ 2

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

Где 0 identity Начальное значение

Ответ 3

Следует отметить, что ЕСЛИ все данные удаляются из таблицы с помощью предложения DELETE (т.е. no WHERE), тогда до тех пор, пока разрешают ему разрешения), и b) нет FKs, ссылающиеся на таблицу (которая, как представляется, здесь), с использованием TRUNCATE TABLE была бы предпочтительнее, так как она делает более эффективную DELETE и сбрасывает семя IDENTITY одновременно. Следующие данные берутся на странице MSDN для ТАБЛИЧКА ПУНКТОВ:

По сравнению с оператором DELETE TRUNCATE TABLE имеет следующие преимущества:

  • Используется меньшее пространство журнала транзакций.

    Оператор DELETE удаляет строки по одному и записывает запись в журнал транзакций для каждой удаленной строки. TRUNCATE TABLE удаляет данные, освобождая страницы данных, используемые для хранения данных таблицы, и записывает только дезадаптации страниц в журнале транзакций.

  • Чаще всего используются блокировки.

    Когда оператор DELETE выполняется с использованием блокировки строк, каждая строка в таблице блокируется для удаления. TRUNCATE TABLE всегда блокирует таблицу (включая блокировку схемы (SCH-M)) и страницу, но не каждую строку.

  • Без исключения в таблице остаются нулевые страницы.

    После выполнения инструкции DELETE таблица может содержать пустые страницы. Например, пустые страницы в куче не могут быть освобождены без по крайней мере исключительной (LCK_M_X) блокировки таблицы. Если операция удаления не использует блокировку таблицы, таблица (куча) будет содержать много пустых страниц. Для индексов операция удаления может оставлять пустые страницы позади, хотя эти страницы будут быстро освобождены процессом очистки фона.

Если таблица содержит столбец идентификатора, счетчик для этого столбца равен reset к начальному значению, определенному для столбца. Если семя не было определено, используется значение по умолчанию 1. Чтобы сохранить счетчик идентификаторов, вместо этого используйте DELETE.

Итак, следующее:

DELETE FROM [MyTable];
DBCC CHECKIDENT ('[MyTable]', RESEED, 0);

Становится просто:

TRUNCATE TABLE [MyTable];

Дополнительную информацию об ограничениях см. в документации TRUNCATE TABLE (см. выше).

Ответ 4

Хотя большинство ответов предлагают RESEED до 0, но во многих случаях нам нужно просто повторно заполнить до следующего доступного Id

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)

Это проверит таблицу и вернется к следующему идентификатору.

Ответ 5

Я попытался ответить @anil shahs и он сбросил личность. Но когда был вставлен новый ряд, он получил identity = 2. Поэтому вместо этого я изменил синтаксис:

DELETE FROM [TestTable]

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

Тогда первый ряд получит тождество = 1.

Ответ 6

Хотя большинство ответов предлагают RESEED - 0, а некоторые считают это недостатком для таблиц TRUNCATED, Microsoft имеет решение, исключающее ID

DBCC CHECKIDENT ('[TestTable]', RESEED)

Это проверит таблицу и reset на следующий ID. Это было доступно с MS SQL 2005 до текущего.

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

Ответ 7

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

  • Сначала включите идентификационную вставку - SET Identity_Insert tblPerson ON
  • В запросе вставки укажите список столбцов Insert into tblPerson(PersonId, Name) values(2, 'John')

После этого у вас есть пробелы в заполненном столбце идентификации, и если вы хотите, чтобы SQL-сервер вычислил значение, отключите Identity_Insert.

SET Identity_Insert tblPerson OFF

=============================

Если вы удалили все строки в таблице и хотите reset значение столбца идентификатора.

Используйте команду CHCCKIDENT DBCC.

DBCC CHECKIDENT(tblPerson, RESEED, 0)

Эта команда будет содержать столбец reset PersonId.

Ответ 8

Это общий вопрос, и ответ всегда один и тот же: не делайте этого. Значения идентичности следует рассматривать как произвольные и, как таковые, не существует "правильного" порядка.

Ответ 9

Команда

выдача 2 может сделать трюк

DBCC CHECKIDENT ('[TestTable]', RESEED,0)
DBCC CHECKIDENT ('[TestTable]', RESEED)

первый reset идентификатор равен нулю, а следующий будет устанавливать его на следующее доступное значение  - jacob

Ответ 10

@jacob

DBCC CHECKIDENT ('[TestTable]', RESEED,0)
DBCC CHECKIDENT ('[TestTable]', RESEED)

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

Ответ 11

Сброс идентификатора столбца с новым идентификатором...

DECLARE @MAX INT
SELECT @MAX=ISNULL(MAX(Id),0) FROM [TestTable]

DBCC CHECKIDENT ('[TestTable]', RESEED,@MAX)

Ответ 12

Truncate таблица, потому что она очищает записи, сбрасывает счетчик и освобождает место на диске.

Delete и CheckIdent должны использоваться только там, где внешние ключи не позволяют вам усекать.

Ответ 13

Запустите этот столбец script to reset. Вам нужно будет внести два изменения. Замените tableXYZ на любую таблицу, которую необходимо обновить. Кроме того, имя столбца идентификации нужно удалить из таблицы temp. Это было мгновенно на столе с 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

Ответ 14

Используйте эту хранимую процедуру:

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

Ответ 15

DBCC CHECKIDENT (<TableName>, reseed, 0)

Это установит текущее значение идентификации равным 0.

При вставке следующего значения значение удостоверения возрастает до 1.

Ответ 16

Для полного удаления строк и сброса счетчика IDENTITY я использую это (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

Ответ 17

Я использую следующий скрипт для этого. Существует только один сценарий, в котором он выдаст "ошибку", если вы удалили все строки из таблицы, а IDENT_CURRENT в настоящее время имеет значение 1, то есть в таблице была только одна строка для начала.

DECLARE @maxID int = (SELECT MAX(ID) FROM dbo.Tbl)
;

IF @maxID IS NULL
    IF (SELECT IDENT_CURRENT('dbo.Tbl')) > 1
        DBCC CHECKIDENT ('dbo.Tbl', RESEED, 0)
    ELSE
        DBCC CHECKIDENT ('dbo.Tbl', RESEED, 1)
    ;
ELSE
    DBCC CHECKIDENT ('dbo.Tbl', RESEED, @maxID)
;

Ответ 18

Повторное заполнение до 0 не очень практично, если вы не чистите стол в целом.

В противном случае ответ Энтони Рэймонда идеален. Сначала получите максимальный столбец идентификаторов, затем начните с макс.

Ответ 19

Всегда лучше использовать TRUNCATE, если это возможно, вместо удаления всех записей, так как он также не использует лог-пространство.

Если нам нужно удалить и нужно reset семя, всегда помните, что если таблица никогда не была заполнена, и вы использовали DBCC CHECKIDENT('tablenem',RESEED,0) то первая запись получит идентификатор = 0 как указано в msdn documentation

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

Ответ 20

Сначала: Спецификация удостоверений Просто: "Нет" → Сохранить проект выполнения базы данных

После этого: Спецификация идентичности Просто: "ДА" → Сохранить проект реализации базы данных

Идентификатор вашей базы данных, PK Начните с 1 →