Ich habe eine Tabelle mit einer Identitätsspalte und möchte einen Block von IDs reservieren, die ich zum Masseneinfügen verwenden kann, während Einfügungen in diese Tabelle weiterhin möglich sind.
Beachten Sie, dass dies Teil einer Masseneinfügung mehrerer Tabellen ist, wobei sich diese anderen Tabellen über eine FK auf diese IDs beziehen. Deshalb muss ich sie blockieren, damit ich die Beziehungen vorher vorbereiten kann.
Ich habe eine Lösung gefunden, die funktioniert, indem sie in einer Transaktion die Tabelle sperrt und dann die Neuaussaat durchführt (was ziemlich schnell ist). Aber es sieht für mich ein bisschen hackig aus - gibt es ein allgemein akzeptiertes Muster dafür?
create table dbo.test
(
id bigint not null primary key identity(1,1),
SomeColumn nvarchar(100) not null
)
Hier ist der Code, um einige IDs auszublenden (Platz zu machen):
declare @numRowsToMakeRoomFor int = 100
BEGIN TRANSACTION;
SELECT MAX(Id) FROM dbo.test WITH ( XLOCK, TABLOCK ) -- will exclusively lock the table whilst this tran is in progress,
--another instance of this query will not be able to pass this line until this instance commits
--get the next id in the block to reserve
DECLARE @firstId BIGINT = (SELECT IDENT_CURRENT( 'dbo.test' ) +1);
--calculate the block range
DECLARE @lastId BIGINT = @firstId + (@numRowsToMakeRoomFor -1);
--reseed the table
DBCC CHECKIDENT ('dbo.test',RESEED, @lastId);
COMMIT TRANSACTION;
select @firstId;
Mein Code besteht aus der Stapelverarbeitung von Datenblöcken in Blöcken von ungefähr 1000. Ich muss insgesamt ungefähr eine Milliarde Zeilen einfügen. Alles funktioniert einwandfrei - die Datenbank ist nicht der Flaschenhals, die Stapelverarbeitung selbst ist rechenintensiv und erfordert, dass ich ein paar Server hinzufüge, um parallel ausgeführt zu werden. Daher muss ich mehr als einen Prozess "Batch Inserting" am gleiche Zeit.
quelle
INSERT .. SELECT ..
mit verwendenOUTPUT
? Kein Verriegeln, kein Nachsaaten. Fügen Sie einfach INSERT ein und holen Sie sich die IDs von OUTPUT, damit Sie sie in den anderen Tabellen verwenden können.Antworten:
Sie können die in SQL Server 2012 eingeführte Prozedur verwenden:
sp_sequence_get_range
Um es zu verwenden, müssen Sie ein SEQUENCE-Objekt erstellen und es als Standardwert anstelle der IDENTITY-Spalte verwenden.
Es gibt ein Beispiel:
Dokumentation: sp_sequence_get_range
quelle