Is there a way to recreate the identity value of a SQL Server table if the statements failed inside a transaction block?
Please go through the code below:
DECLARE @IdentityTable AS TABLE (ID INT IDENTITY(1, 1), Description VARCHAR(50))
INSERT INTO @IdentityTable (Description)
VALUES('Test1')
BEGIN TRY
BEGIN TRANSACTION IdentityTest
INSERT INTO @IdentityTable (Description)
VALUES('Test2')
INSERT INTO @IdentityTable (Description)
VALUES(1/0)
COMMIT TRANSACTION IdentityTest
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION IdentityTest
END CATCH
INSERT INTO @IdentityTable (Description)
VALUES('Test4')
SELECT * FROM @IdentityTable
Identity No 3 is lost due to ROLLBACK TRANSACTION
. Is it possible to regain it?
You're trying to use the IDENTITY
property to generate consecutive numbers, and maintain it; that isn't what IDENTITY
is for. It's designed to provide an incrementing value based on the current seed (on it's own (without a PRIMARY KEY
constraint or UNIQUE INDEX
), it doesn't even guarantee uniqueness as the seed could be changed (thanks HoneyBadger for reminding me so early in the morning)).
If an INSERT
fails, the value of the IDENTITY
will still be incremented. Also, if you were to DELETE
a row from a table, that would not cause every "latter" row to have their ID's updated accordingly; thus you would also have a gap then.
The only guaranteed way of ensuring you get an incrementing value is by using a function like ROW_NUMBER
at run time. For example:
SELECT ROW_NUMBER() OVER (ORDER BY ID) AS cID,
Description
FROM YourTable;
The Remarks section of the documentation specifically states that consecutive values are not guarenteed:
Identity columns can be used for generating key values. The identity property on a column guarantees the following:
...
Consecutive values within a transaction – A transaction inserting multiple rows is not guaranteed to get consecutive values for the rows because other concurrent inserts might occur on the table. If values must be consecutive then the transaction should use an exclusive lock on the table or use the SERIALIZABLE isolation level.
Consecutive values after server restart or other failures – SQL Server might cache identity values for performance reasons and some of the assigned values can be lost during a database failure or server restart. This can result in gaps in the identity value upon insert. If gaps are not acceptable then the application should use its own mechanism to generate key values. Using a sequence generator with the NOCACHE option can limit the gaps to transactions that are never committed.
Reuse of values – For a given identity property with specific seed/increment, the identity values are not reused by the engine. If a particular insert statement fails or if the insert statement is rolled back then the consumed identity values are lost and will not be generated again. This can result in gaps when the subsequent identity values are generated.