Setzen Sie AutoIncrement in SQL Server nach dem Löschen zurück

265

Ich habe einige Datensätze aus einer Tabelle in einer SQL Server-Datenbank gelöscht. Jetzt gehen die IDs von 101 auf 1200. Ich möchte die Datensätze erneut löschen, aber ich möchte, dass die IDs auf 102 zurückgehen. Gibt es eine Möglichkeit, dies in SQL Server zu tun?

Jumbojs
quelle
46
Bitte sagen Sie nicht "Tu es nicht". Ich hasse es, wenn ich frage, wie ich etwas machen soll und alles, was ich bekomme, ist, es nicht zu tun. Ja, das Zurücksetzen der Identität kann zu Fremdschlüsselproblemen führen, jedoch nur, wenn Sie Ihre Datenbank und Ihr Programm nicht entsprechend kennen. Es gibt sehr gute Gründe, eine Identität nach einem geplanten Löschen zurückzusetzen - sie werden als Auditoren bezeichnet. Auditoren hassen es, Lücken zu sehen, also füllen Sie sie, tun Sie dies auf kontrollierte Weise und stellen Sie sicher, dass Fremdschlüsselbeschränkungen eingehalten werden.
6
@spyder, wussten Sie, dass Sie Lücken haben, wenn eine Datensatzeinfügung nicht nur zum Löschen zurückgesetzt wird? Sie können Lücken mit einer automatischen Erhöhung nicht vermeiden, und es ist dumm, es zu versuchen. Ich habe für eine Prüfungsagentur gearbeitet, und kompetente Prüfer können sich dies erklären lassen. Wenn Sie über geeignete Audittabellen verfügen, können diese außerdem sehen, was mit diesen Datensätzen passiert ist. Oder wenn es aus rechtlichen Gründen niemals Lücken geben darf (es gibt einige Fälle davon), würde nur ein inkompetenter Entwickler eine automatische Erhöhung verwenden, und die Prüfer sind zu Recht verärgert.
HLGEM

Antworten:

454

Geben Sie den folgenden Befehl ein, um mytable neu zu setzen und bei 1 zu beginnen:

DBCC CHECKIDENT (mytable, RESEED, 0)

Lesen Sie darüber in den Online-Büchern (BOL, SQL-Hilfe). Achten Sie auch darauf, dass Sie keine höheren Datensätze als den von Ihnen festgelegten Startwert haben.

Robert Wagner
quelle
4
... weil die IDs dieser Datensätze gerne wiederverwendet werden, was zu einem schlechten Durcheinander führt.
Nalply
3
Um IDs bei 1 zu starten, müssen Sie 0: DBCC CHECKIDENT (mytable, RESEED, 0)
Ryan Lundy
7
"DBCC CHECKIDENT (table_name)" setzt den Startwert auf die höchste Identität in der Tabelle, als Sie nicht "vorsichtig" sein müssen
user1027167
4
@ user1027167 Nein, deine Antwort hat bei mir nicht funktioniert. Die höchste ID, die intern gespeichert wurde, wurde immer weiter erhöht. Ich musste in meinem Fall explizit "RESEED, 18" verwenden, um "19" als nächste ID zu erhalten. Ohne es weiter glücklich auf "29" zu erhöhen.
Matthis Kohli
DBCC CHECKIDENT (Tabellenname) ändert den Startwert nur, wenn der Identitätswert niedriger als der Maximalwert in der Spalte ist. Wenn also der Identitätswert bereits größer ist als im Fall @MatthisKohli, muss das explizite Reseed aufgerufen werden.
Martheen
82
DBCC CHECKIDENT('databasename.dbo.tablename', RESEED, number)

Wenn number = 0 ist, enthält das Feld für die automatische Inkrementierung beim nächsten Einfügen den Wert 1

Wenn number = 101, enthält das Auto-Inkrement-Feld beim nächsten Einfügen den Wert 102


Einige zusätzliche Informationen ... Kann für Sie nützlich sein

Bevor Sienumber in der obigen Abfrage die automatische Inkrementierung angeben, müssen Sie sicherstellen, dass die Spalte für die automatische Inkrementierung Ihrer vorhandenen Tabelle Werte enthält, die kleiner sind als diese number.

Um den Maximalwert einer Spalte (Spaltenname) aus einer Tabelle (Tabelle 1) abzurufen, können Sie die folgende Abfrage verwenden

 SELECT MAX(column_name) FROM table1
Fathah Rehman P.
quelle
36

halb idiotensicher:

declare @max int;  
select @max = max(key) from table;  
dbcc checkident(table,reseed,@max)

http://sqlserverplanet.com/tsql/using-dbcc-checkident-to-reseed-a-table-after-delete

user423430
quelle
1
"DBCC CHECKIDENT (table_name)" macht dasselbe (möglich ohne Rennbedingungen)
user1027167
2
@ user1027167 In den Dokumenten wird angegeben, ob der aktuelle Identitätswert für eine Tabelle kleiner als der in der Identitätsspalte gespeicherte maximale Identitätswert ist. Dies gilt nicht für die Bereinigung nach dem Löschen von Daten (Wiederverwendung von IDs - häufig eine schlechte Idee). Verifiziert unter SQL 2008
user423430
1
Die beste systematische und automatische Antwort. Bravo!
Mehdi Khademloo
11

Wenn Sie MySQL verwenden, versuchen Sie Folgendes:

ALTER TABLE tablename AUTO_INCREMENT = 1
xaa
quelle
3
Dies ist eine Antwort für MySQL. OP fragt nach MSSQL.
reformiert
Die Frage ist über MS SQL Server
Saher Ahwal
6

Löschen Sie alle Tabellen in einer Datenbank und setzen Sie sie erneut ein.

    USE [DatabaseName]
    EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"       -- Disable All the constraints
    EXEC sp_MSForEachTable "DELETE FROM ?"    -- Delete All the Table data
    Exec sp_MSforeachtable 'DBCC CHECKIDENT(''?'', RESEED, 0)' -- Reseed All the table to 0
    Exec sp_msforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"  -- Enable All  the constraints back

-- You may ignore the errors that shows the table without Auto increment field.
BMG
quelle
6

Ich habe es herausgefunden. Es ist:

 DBCC CHECKIDENT ('tablename', RESEED, newseed)
Jumbojs
quelle
4

Basierend auf der akzeptierten Antwort für diejenigen, die auf ein ähnliches Problem gestoßen sind, mit vollständiger Schemaqualifikation:

( [MyDataBase].[MySchemaName].[MyTable]) ... führt zu einem Fehler, Sie müssen sich im Kontext dieser Datenbank befinden

Das heißt, Folgendes wird einen Fehler auslösen:

DBCC CHECKIDENT ([MyDataBase].[MySchemaName].[MyTable], RESEED, 0)

Schließen Sie stattdessen den vollständig qualifizierten Tabellennamen in einfache Anführungszeichen ein:

DBCC CHECKIDENT ('[MyDataBase].[MySchemaName].[MyTable]', RESEED, 0)
user919426
quelle
4

In mehreren Antworten wird empfohlen, eine Aussage wie die folgende zu verwenden:

DBCC CHECKIDENT (mytable, RESEED, 0)

Aber das OP sagte "löschte einige Datensätze", die möglicherweise nicht alle sind, so dass ein Wert von 0 nicht immer der richtige ist. In einer anderen Antwort wurde vorgeschlagen, den maximalen aktuellen Wert automatisch zu ermitteln und auf diesen Wert zurückzusetzen. Dies führt jedoch zu Problemen, wenn die Tabelle keine Datensätze enthält, und daher gibt max () NULL zurück. Ein Kommentar schlug vor, einfach zu verwenden

DBCC CHECKIDENT (mytable)

um den Wert zurückzusetzen, aber ein anderer Kommentar gab korrekt an, dass dies den Wert nur auf das Maximum erhöht, das bereits in der Tabelle enthalten ist; Dies verringert den Wert nicht, wenn er bereits höher als das Maximum in der Tabelle ist, was das OP tun wollte.

Eine bessere Lösung kombiniert diese Ideen. Der erste CHECKIDENT setzt den Wert auf 0 zurück und der zweite setzt ihn auf den höchsten aktuell in der Tabelle enthaltenen Wert zurück, falls Datensätze in der Tabelle vorhanden sind:

DBCC CHECKIDENT (mytable, RESEED, 0)
DBCC CHECKIDENT (mytable)

Stellen Sie, wie in mehreren Kommentaren angegeben, sicher, dass in anderen Tabellen keine Fremdschlüssel vorhanden sind, die auf die gelöschten Datensätze verweisen. Andernfalls verweisen diese Fremdschlüssel auf Datensätze, die Sie nach dem erneuten Einfügen der Tabelle erstellt haben. Dies ist mit ziemlicher Sicherheit nicht das, was Sie sich vorgestellt haben.

Michael Rodby
quelle
4

Ich möchte diese Antwort hinzufügen, da der DBCC CHECKIDENTAnsatz Probleme verursacht, wenn Sie Schemas für Tabellen verwenden. Verwenden Sie dies, um sicherzugehen:

DECLARE @Table AS NVARCHAR(500) = 'myschema.mytable';
DBCC CHECKIDENT (@Table, RESEED, 0);

Wenn Sie den Erfolg des Vorgangs überprüfen möchten, verwenden Sie

SELECT IDENT_CURRENT(@Table);

welches 0im obigen Beispiel ausgegeben werden sollte .

Alexander Schmidt
quelle
1

Sie möchten dies im Allgemeinen nicht tun. Reseed kann zu Datenintegritätsproblemen führen. Es ist wirklich nur für die Verwendung auf Entwicklungssystemen vorgesehen, auf denen Sie alle Testdaten löschen und von vorne beginnen. Es sollte nicht in einem Produktionssystem verwendet werden, falls nicht alle zugehörigen Datensätze gelöscht wurden (nicht jede Tabelle, die in einer Fremdschlüsselbeziehung stehen sollte, ist!). Sie können dabei ein Durcheinander verursachen, insbesondere wenn Sie dies nach jedem Löschen regelmäßig tun möchten. Es ist eine schlechte Idee, sich über Lücken in Ihren Identitätsfeldwerten Gedanken zu machen.

HLGEM
quelle
6
Ich werde es nicht die ganze Zeit benutzen und es war nur auf einer Test-Datenbank.
Jumbojs
0

Was ist damit?

ALTER TABLE `table_name`
  MODIFY `id` int(12) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=0;

Dies ist eine schnelle und einfache Möglichkeit, das automatische Inkrement auf 0 oder eine beliebige Zahl zu ändern. Ich habe das herausgefunden, indem ich eine Datenbank exportiert und den Code selbst gelesen habe.

Sie können es auch so schreiben, um es zu einer einzeiligen Lösung zu machen:

ALTER TABLE `table_name` MODIFY `id` int(12) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=0;
Victor Resnov
quelle
1
Vielen Dank für dieses Code-Snippet, das möglicherweise nur begrenzte und sofortige Hilfe bietet. Eine richtige Erklärung würde ihren langfristigen Wert erheblich verbessern, indem sie zeigt, warum dies eine gute Lösung für das Problem ist, und es für zukünftige Leser mit anderen, ähnlichen Fragen nützlicher machen. Bitte bearbeiten Sie Ihre Antwort, um eine Erklärung hinzuzufügen, einschließlich der von Ihnen getroffenen Annahmen.
Auf Wiedersehen StackExchange