In SQL 2005 und höher gibt es einen Trick, um dieses Problem zu lösen, ohne die Datenseiten der Tabelle zu ändern. Dies ist wichtig für große Tabellen, bei denen das Anfassen jeder Datenseite Minuten oder Stunden dauern kann. Der Trick funktioniert auch, wenn die Identitätsspalte ein Primärschlüssel ist, Teil eines geclusterten oder nicht geclusterten Indexes ist oder andere Probleme auftauchen, die die einfachere Lösung "Spalte hinzufügen/entfernen/umbenennen" zum Scheitern bringen können.
Hier ist der Trick: Sie können die SQL Server-Funktion ALTER TABLE...SWITCH Anweisung können Sie das Schema einer Tabelle ändern, ohne die Daten zu ändern, d.h. Sie können eine Tabelle mit IDENTITY durch ein identisches Tabellenschema, aber ohne IDENTITY-Spalte, ersetzen. Der gleiche Trick funktioniert, um IDENTITY zu einer vorhandenen Spalte hinzuzufügen.
Normalerweise, ALTER TABLE...SWITCH wird verwendet, um eine volle Partition in einer partitionierten Tabelle effizient durch eine neue, leere Partition zu ersetzen. Es kann aber auch in nicht partitionierten Tabellen verwendet werden.
Ich habe diesen Trick verwendet, um in weniger als 5 Sekunden eine Spalte einer Tabelle mit 2,5 Milliarden Zeilen von IDENTITY in eine Non-IDENTITY-Spalte zu konvertieren (um eine mehrstündige Abfrage auszuführen, deren Abfrageplan für Non-IDENTITY-Spalten besser funktionierte), und dann die IDENTITY-Einstellung wiederhergestellt, wiederum in weniger als 5 Sekunden.
Hier ist ein Code-Beispiel, wie es funktioniert.
CREATE TABLE Test
(
id int identity(1,1),
somecolumn varchar(10)
);
INSERT INTO Test VALUES ('Hello');
INSERT INTO Test VALUES ('World');
-- copy the table. use same schema, but no identity
CREATE TABLE Test2
(
id int NOT NULL,
somecolumn varchar(10)
);
ALTER TABLE Test SWITCH TO Test2;
-- drop the original (now empty) table
DROP TABLE Test;
-- rename new table to old table's name
EXEC sp_rename 'Test2','Test';
-- update the identity seed
DBCC CHECKIDENT('Test');
-- see same records
SELECT * FROM Test;
Dies ist natürlich aufwändiger als die Lösungen in den anderen Antworten, aber wenn Ihr Tisch groß ist, kann dies ein echter Lebensretter sein. Es gibt einige Vorbehalte:
- Soweit ich weiß, ist die Identität das Einzige, was Sie mit dieser Methode an den Spalten Ihrer Tabelle ändern können. Das Hinzufügen/Entfernen von Spalten, das Ändern der Nullbarkeit usw. ist nicht erlaubt.
- Sie müssen die ausländischen Schlüssel vor dem Wechsel ablegen und sie danach wiederherstellen.
- Dasselbe gilt für WITH SCHEMABINDING-Funktionen, Ansichten usw.
- die Indizes der neuen Tabelle müssen genau übereinstimmen (gleiche Spalten, gleiche Reihenfolge usw.)
- Alte und neue Tabellen müssen sich in der gleichen Dateigruppe befinden.
- Funktioniert nur auf SQL Server 2005 oder höher
- Ich habe bisher geglaubt, dass dieser Trick nur auf den Enterprise- oder Developer-Editionen von SQL Server funktioniert (weil Partitionen nur in den Enterprise- und Developer-Versionen unterstützt werden), aber Mason G. Zhwiti sagt in seinem Kommentar unten, dass er auch in der SQL Standard Edition funktioniert. Ich nehme an, dass dies bedeutet, dass die Beschränkung auf Enterprise oder Developer nicht für ALTER TABLE...SWITCH gilt.
Es gibt eine gute Artikel im TechNet in dem die oben genannten Anforderungen im Einzelnen aufgeführt sind.
UPDATE - Eric Wu hatte unten einen Kommentar, der wichtige Informationen zu dieser Lösung enthält. Ich kopiere ihn hier, um sicherzustellen, dass er mehr Aufmerksamkeit erhält:
Hier gibt es noch einen weiteren Vorbehalt, der erwähnenswert ist. Obwohl die neue Tabelle gerne Daten aus der alten Tabelle erhält und alle neuen Zeilen neuen Zeilen nach einem identischen Muster eingefügt werden, werden sie bei 1 beginnen und möglicherweise abbrechen, wenn die besagte Spalte ein Primärschlüssel ist. Betrachten Sie die Ausführung DBCC CHECKIDENT('<newTableName>')
unmittelbar nach Wechsel. Siehe msdn.microsoft.com/de-us/library/ms176057.aspx für mehr Informationen.
Wenn die Tabelle aktiv mit neuen Zeilen erweitert wird (was bedeutet, dass Sie nicht viel oder gar keine Ausfallzeit zwischen dem Hinzufügen von IDENTITY und dem Hinzufügen neuer Zeilen haben), dann sollten Sie anstelle von DBCC CHECKIDENT
müssen Sie den Identitäts-Seed-Wert im neuen Tabellenschema manuell so einstellen, dass er größer ist als die größte vorhandene ID in der Tabelle, z. B. IDENTITY (2435457, 1)
. Möglicherweise können Sie sowohl die ALTER TABLE...SWITCH
und die DBCC CHECKIDENT
in einer Transaktion (oder nicht - ich habe das nicht getestet), aber es scheint, dass es einfacher und sicherer ist, den Seed-Wert manuell zu setzen.
Wenn der Tabelle keine neuen Zeilen hinzugefügt werden (oder nur gelegentlich, z. B. bei einem täglichen ETL-Prozess), tritt diese Race Condition natürlich nicht auf. DBCC CHECKIDENT
ist in Ordnung.