Resetuj seed tożsamości po usunięciu rekordów w SQL Server

Wstawiłem rekordy do tabeli bazy danych SQL Server. Tabela miała zdefiniowany klucz podstawowy, a zalążek tożsamości Auto increment jest ustawiony na "Yes". Dzieje się tak przede wszystkim dlatego, że w SQL Azure każda tabela musi mieć zdefiniowany klucz podstawowy i tożsamość.

Ale ponieważ muszę usunąć niektóre rekordy z tabeli, zalążek tożsamości dla tych tabel zostanie zakłócony, a Kolumna indeksu (która jest automatycznie generowana z przyrostem 1) zostanie zakłócona.

Jak mogę zresetuj kolumnę tożsamości po usunięciu rekordów, aby kolumna miała kolejność rosnącą w porządku liczbowym?

Kolumna identity nie jest używana jako klucz obcy nigdzie w bazie danych.

Author: dakab, 2014-02-17

18 answers

The DBCC CHECKIDENT polecenie zarządzania służy do resetowania licznika tożsamości. Składnia polecenia to:

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

Przykład:

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

Nie był obsługiwany w poprzednich wersjach usługi Azure SQL Database, ale jest obsługiwany teraz.


Proszę zauważyć, że argument new_reseed_value jest różny w różnych wersjach SQL Server zgodnie z dokumentacją :

Jeśli wiersze są obecne w tabeli, następny wiersz jest wstawiany z wartością new_reseed_value. W wersja SQL Server 2008 R2 i wcześniejsza, następny wstawiony wiersz używa new_reseed_value + bieżącej wartości przyrostu.

Jednak uważam, że ta informacja wprowadza w błąd (w rzeczywistości jest to po prostu błędne), ponieważ obserwowane zachowanie wskazuje, że przynajmniej SQL Server 2012 nadal używa new_reseed_value + bieżąca logika wartości przyrostu. Microsoft zaprzecza nawet własnemu Example C znalezionemu na tej samej stronie:

C. wymuszenie aktualnej tożsamości wartość do nowej wartości

Poniższy przykład wymusza aktualną wartość tożsamości w Kolumna AddressTypeID w tabeli AddressType do wartości 10. Ponieważ tabela zawiera istniejące wiersze, następny wstawiony wiersz będzie używał 11 jako wartość, czyli nową bieżącą wartość przyrostu zdefiniowaną dla wartość kolumny plus 1.

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

Nadal, to wszystko pozostawia opcję dla różnych zachowań na nowszych wersjach SQL Server. Chyba jedynym sposobem na upewnienie się, dopóki Microsoft wyjaśnij rzeczy we własnej dokumentacji, jest zrobić rzeczywiste testy przed użyciem.

 859
Author: Petr Abdulin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-02 05:19:57
DBCC CHECKIDENT ('TestTable', RESEED, 0)
GO

Gdzie 0 jest identity wartością początkową

 179
Author: anil shah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-26 19:06:33

Należy zauważyć, że jeśli wszystkie danych są usuwane z tabeli za pomocą DELETE (tj. klauzuli no WHERE), to tak długo, jak zezwalają na to uprawnienia a) i b) nie ma FKs odwołujących się do tabeli (co wydaje się mieć miejsce w tym przypadku), użycie TRUNCATE TABLE byłoby preferowane, ponieważ czyni to bardziej wydajne DELETE i resetuje ziarno IDENTITY w tym samym czasie. Poniższe dane pochodzą ze strony MSDN dla TRUNCATE TABLE :

W porównaniu z Polecenie DELETE, tabela TRUNCATE ma następujące zalety:

  • Zużywa się mniej miejsca w dzienniku transakcji.

    Instrukcja DELETE usuwa wiersze pojedynczo i zapisuje wpis w dzienniku transakcji dla każdego usuniętego wiersza. Tabela TRUNCATE usuwa dane poprzez dealokację stron danych używanych do przechowywania danych tabeli i zapisuje tylko dealokacje stron w dzienniku transakcji.

  • Zazwyczaj stosuje się mniej zamków.

    Gdy Polecenie DELETE jest wykonywane za pomocą blokady wierszy, każdy wiersz w tabeli jest blokowany do usunięcia. TRUNCATE TABLE zawsze blokuje tabelę (włącznie z blokadą schematu (SCH-M)) i stronę, ale nie każdy wiersz.

  • Bez wyjątku w tabeli pozostaje zero stron.

    Po wykonaniu polecenia DELETE, tabela może nadal zawierać puste strony. Na przykład puste strony w stercie nie mogą być rozdzielone bez co najmniej wyłącznej blokady tabeli (LCK_M_X). Jeśli usunąć operacja nie używa blokady tabeli, tabela (sterta) będzie zawierać wiele pustych stron. W przypadku Indeksów operacja usuwania może pozostawić puste strony, chociaż strony te zostaną szybko rozdzielone przez proces czyszczenia tła.

Jeśli tabela zawiera kolumnę identity, licznik dla tej kolumny jest resetowany do wartości początkowej zdefiniowanej dla kolumny. Jeśli nie zdefiniowano nasion, używana jest wartość domyślna 1. Aby zachować licznik tożsamości, użyj Usuń zamiast tego.

Tak więc:

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

Staje się tylko:

TRUNCATE TABLE [MyTable];

Proszę zapoznać się z dokumentacją TRUNCATE TABLE (link powyżej), aby uzyskać dodatkowe informacje na temat ograniczeń itp.

 67
Author: Solomon Rutzky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-10 17:52:27

Próbowałem odpowiedzieć i to zresetowało tożsamość. Ale kiedy wstawiono nowy wiersz, otrzymano identity = 2. Zamiast tego zmieniłem składnię na:

DELETE FROM [TestTable]

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

Wtedy pierwszy wiersz otrzyma identity = 1.

 55
Author: Mikael Engver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-25 15:52:42

Chociaż większość odpowiedzi sugeruje ponowne przesłanie do 0, ale wiele razy musimy po prostu ponownie przesłać do następnego Id dostępnego

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)

Spowoduje to sprawdzenie tabeli i zresetowanie do następnego ID.

 54
Author: Atal Kishore,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-31 15:28:26

Chociaż większość odpowiedzi sugeruje RESEED do 0, a niektórzy uważają to za wadę tabel TRUNCATED, Microsoft ma rozwiązanie, które wyklucza ID

DBCC CHECKIDENT ('[TestTable]', RESEED)

Spowoduje to sprawdzenie tabeli i zresetowanie do następnego ID. Jest to dostępne od MS SQL 2005 do current.

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

 13
Author: SollyM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-11 09:47:21

Aby jawnie podać wartość kolumny identity

  1. pierwsza turn on identity insert - SET Identity_Insert tblPerson ON
  2. w zapytaniu Wstaw podaj listę kolumn Insert into tblPerson(PersonId, Name) values(2, 'John')

Następnie masz wypełnione luki w kolumnie tożsamości i jeśli chcesz, aby SQL server obliczył wartość, Wyłącz Identity_Insert.

SET Identity_Insert tblPerson OFF

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

Jeśli usunąłeś wszystkie wiersze w tabeli i chcesz zresetować wartość kolumny identity.

Użyj DBCC / Align = "left" /

DBCC CHECKIDENT(tblPerson, RESEED, 0)

To polecenie zresetuje kolumnę tożsamości osoby.

 8
Author: Rae Lee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-28 04:53:54

@Jakub

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

Zadziałało dla mnie, po prostu musiałem najpierw wyczyścić wszystkie wpisy z tabeli, a następnie dodać powyższe w punkcie wyzwalania po usunięciu. Teraz za każdym razem, gdy usuwam wpis jest pobierany stamtąd.

 5
Author: epic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-06 11:46:05

To częste pytanie i odpowiedź jest zawsze taka sama: nie rób tego. Wartości tożsamości należy traktować jako arbitralne i jako takie nie ma "poprawnej" kolejności.

 4
Author: Ben Thul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-17 15:00:53

Wydanie 2 komendy może załatwić sprawę

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

Pierwszy zresetuje tożsamość do zera, a następny ustawi ją na następną dostępną wartość -- Jakub

 4
Author: jacob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-12 07:58:00

Tabela Truncate jest preferowana, ponieważ czyści rekordy, resetuje licznik i odzyskuje przestrzeń dis.

Delete i CheckIdent powinny być używane tylko wtedy, gdy klucze obce uniemożliwiają obcinanie

 3
Author: Dyna Dave,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-19 16:31:36

Zresetuj kolumnę tożsamości z nowym id...

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

DBCC CHECKIDENT ('[TestTable]', RESEED,@MAX)
 3
Author: Mukesh Pandey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-08 10:20:38

Uruchom ten skrypt, aby zresetować kolumnę tożsamości. Musisz wprowadzić dwie zmiany. Zastąp tableXYZ dowolną tabelą, którą chcesz zaktualizować. Ponadto nazwa kolumny tożsamości musi zostać usunięta z tabeli tymczasowej. To było natychmiastowe na tabeli z 35,000 wierszy i 3 kolumny. Oczywiście, wykonaj kopię zapasową tabeli i najpierw wypróbuj to w środowisku testowym.


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
 2
Author: Matthew Baic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-05 17:45:50

Użyj tej procedury składowanej:

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'
Tylko wracam do mojej odpowiedzi. Natknąłem się na dziwne zachowanie w sql server 2008 r2, o którym powinieneś być świadomy.
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

Pierwszy wybór daje 0, Item 1.

Drugi produkuje 1, Item 1. Jeśli reset wykonasz zaraz po utworzeniu tabeli, następną wartością będzie 0. Szczerze mówiąc, nie dziwię się, że Microsoft nie może tego zrobić dobrze. Odkryłem to, ponieważ mam plik skryptu, który zapełnia tabele referencyjne, które czasami Uruchom po ponownym utworzeniu tabel, a czasami gdy tabele są już utworzone.

 1
Author: costa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-03 00:38:02
DBCC CHECKIDENT (<TableName>, reseed, 0)

Spowoduje ustawienie bieżącej wartości tożsamości na 0.

Po wstawieniu następnej wartości wartość tożsamości jest zwiększana do 1.

 0
Author: Bimzee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-02 07:11:09

Dla kompletnego usuwania wierszy i resetowania liczby tożsamości, używam tego (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
 0
Author: Fandango68,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-23 05:16:20

Zawsze lepiej jest używać TRUNCATE , gdy jest to możliwe, zamiast usuwać wszystkie rekordy, ponieważ nie używa również przestrzeni logów.

W przypadku, gdy potrzebujemy delete i musimy zresetować seed, zawsze pamiętaj, że jeśli tabela nigdy nie była wypełniona i użyłeś DBCC CHECKIDENT('tablenem',RESEED,0) wtedy pierwszy rekord otrzyma identity = 0 jak podano w msdn documentation

W Twoim przypadku tylko Odbuduj indeks i nie martw się o utratę szereg tożsamości, gdyż jest to częsty scenariusz.

 -2
Author: Abdul Hannan Ijaz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-05 09:19:47

Najpierw: Specyfikacja Tożsamości Tylko: "Nie" > > Zapisz Bazę Danych Wykonaj Projekt

Następnie: Specyfikacja tożsamości tylko: "tak" > > Zapisz bazę danych wykonaj Projekt

Twój identyfikator bazy danych, PK zaczyna się od 1 > >

 -2
Author: Pratik Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-28 05:10:56