SQLServerCentral Article

Tip: Resetting Identity Fields

,

I have been cleaning up some existing code scripts and making them into standardized stored procedures.  Two of my scripts deal with backing out ETL data from raw and temp tables that was transformed incorrectly during an ETL routine.  Part of the code I use will reseed the identity field for the raw and temp tables to eliminate discontinuities in the identity field.  The original code was using a construct such as:

Declare @MaxIdentityValue BigInt
Set @MaxIdentityValue = (Select Top 1 IdentityField
                          From MyTable
                          Order By IdentityField Desc
                         )
DBCC CHECKIDENT(MyTable, RESEED, @MaxIdentityValue)

This could have been better served by

Declare @MaxIdentityValue BigInt
Set @MaxIdentityValue = (Select Max(IdentityField) 
                          From MyTable
                         )
DBCC CHECKIDENT(MyTable, RESEED, @MaxIdentityValue)

But I took some time and dove into what BOL had to say about DBCC CHECKIDENT and discovered this passage:

When the current identity value is larger than the maximum value in the table, then:

Execute DBCC CHECKIDENT (table_name, NORESEED) to determine the current maximum value in the column, and then specify that value as the new_reseed_value in a DBCC CHECKIDENT (table_name, RESEED, new_reseed_value) command.

or

Execute DBCC CHECKIDENT (table_name, RESEED, new_reseed_value) with new_reseed_value set to a very low value, and then run DBCC CHECKIDENT (table_name, RESEED) to correct the value.

Using this tip, I ran the following test:

If Exists(Select Name
           From sys.objects 
           Where name = 'TestReseed' 
           And type = 'U'
          )
 Drop Table TestReseed
GO
Create Table TestReseed(Fld1 Int Identity(1,1), Fld2 Int)
GO
Declare @ReseedValue Int = 0
While @ReseedValue < 10
 BEGIN
  Set @ReseedValue = @ReseedValue + 1
  Insert Into TestReseed(Fld2)
   Values(@ReseedValue)
 END
Select * From TestReseed
/* Results
Fld1 Fld2
1    1
2    2
3    3
4    4
5    5
6    6
7    7
8    8
9    9
10   10
*/

The identity field matches our control field.  Now let's delete 5 rows:

Delete From TestReseed Where Fld1 > 5
Select * From TestReseed
/* Results
Fld1 Fld2
1    1
2    2
3    3
4    4
5    5
*/

Now let's add in 5 rows again:

Declare @ReseedValue Int = 0
While @ReseedValue < 5
 BEGIN
  Set @ReseedValue = @ReseedValue + 1
  Insert Into TestReseed(Fld2)
   Values(@ReseedValue)
 END
 
/* Results
Fld1 Fld2
1    1
2    2
3    3
4    4
5    5
11   1
12   2
13   3
14   4
15   5
*/

Notice that the identity field now has a discontinuity in it between 5 and 11.  Now take out the top 5 rows again.

  Delete From TestReseed Where Fld1 > 5

At this point we can reset the identity column to where we want it with the following:

DBCC CHECKIDENT("TestReseed",RESEED,1)
DBCC CHECKIDENT("TestReseed",RESEED)
/* Results
Checking identity information: current identity value '20', current column value '1'.
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
Checking identity information: current identity value '1', current column value '5'.
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
  */

Now we add back in our 5 rows:

Declare @ReseedValue Int = 0
While @ReseedValue < 5
 BEGIN
  Set @ReseedValue = @ReseedValue + 1
  Insert Into TestReseed(Fld2)
    Values(@ReseedValue)
 END
Select * From TestReseed
/* Results
1  1
2  2
3  3
4  4
5  5
6  1
7  2
8  3
9  4
10 5
*/

We see that with two simple lines of code, the identity value is set to the next contiguous value without having to determine the reseed value in a parameter.

Rate

3.29 (21)

You rated this post out of 5. Change rating

Share

Share

Rate

3.29 (21)

You rated this post out of 5. Change rating