21

I recently migrated from a PostgreSQL database to a SQL Server database. To switch the data over I had to enable IDENTITY_INSERT. Well come to find out that I get all sorts of strange errors due to duplicate identity values(which are set as primary keys) upon doing an insert in any of the tables.

I have quite a few tables. What would be the easiest way of automatically reseeding the identity of every table so that it is after max(RID)?

Earlz
  • 62,085
  • 98
  • 303
  • 499

5 Answers5

34

Use the information in this link in combination with a SQL function that gets the max(RID) from each table that you need to reset. For instance, if you want to start your primary key seed at 25000, use the code below (StartSeedValue - 1)

DBCC CHECKIDENT('myTable', RESEED, 24999)

So in combination, you should end up with somethink like this

DECLARE @maxVal INT
SELECT @maxVal = ISNULL(max(ID),0)+1 from mytable
DBCC CHECKIDENT('mytable', RESEED, @maxVal)

Sorry for the Pseudo-code, been awhile since I have written a SQL function :)

EDIT:

Thanks for the catch, changed the INTEGER to INT

USE YourDBName
GO 
SELECT *
FROM sys.Tables
GO 

This will give you a listing of all user tables in the database. Use this query as your 'loop' and that should allow to reset the seeds on all tables.

Community
  • 1
  • 1
Tommy
  • 39,592
  • 10
  • 90
  • 121
  • 1
    Is there any way to do this for every table automatically though? – Earlz May 27 '10 at 18:47
  • +1, but integer is not a sql server data type, so use: `DECLARE @maxVal INT` and to populate a variable use: `SELECT @maxVal = ISNULL(max(ID),0)+1 from mytable` – KM. May 27 '10 at 18:50
  • @KM good note on the ISNULL check but `integer` is recognized by SQL Server 2008 – Earlz May 27 '10 at 18:54
  • integer is not supported in pre SQl Server 2008, it is INT, and question did not specify 2008. – KM. May 27 '10 at 18:55
  • 3
    SELECT @maxVal = ISNULL(max(ID),0) from mytable if you want to start ID from 1 – Faiz Nov 05 '14 at 11:39
18

Tommy's answer is correct, but if I am reading documentation right this can be simplified to just:

DBCC CHECKIDENT ('myTable')

According to documentation:

If the current identity value for a table is less than the maximum identity value stored in the identity column, it is reset using the maximum value in the identity column.

This saves you from the need ot look up maximum ID manually, and is supported from SQL Server 2005 onwards.

This should work in original OP case. Documentation mentions however two cases where this will not work, and you have to fall-back to Tommy's solution with looking maximum ID value manually:

  • The current identity value is larger than the maximum value in the table.
  • All rows are deleted from the table.
Sebastian K
  • 6,235
  • 1
  • 43
  • 67
  • 2
    and even more automatically to all tables : `Exec sp_MSforeachtable 'DBCC CHECKIDENT(''?'')'` – Aristos Feb 11 '16 at 09:08
6

Perhaps the easiest way (as crazy as this sounds and as code-smelly as it looks) is to just run DBCC CHECKIDENT twice like this:

-- sets all the seeds to 1
exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT (''?'', RESEED, 1)'

-- run it again to get MSSQL to figure out the MAX/NEXT seed automatically
exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT (''?'')'

Done.

If you want, you can run it once more to see what all the seeds were set to:

-- run it again to display what the seeds are now set to
exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT (''?'')'

This is just a creative way to take advantage of the comment from the documentation:

If the current identity value for a table is less than the maximum identity value stored in the identity column, it is reset using the maximum value in the identity column.

101010
  • 14,866
  • 30
  • 95
  • 172
0

Rollback cases -

i've testing in my database and only works if i use this code listed here before (with a modification on the +1 - we don't need this).

DECLARE @maxVal INT
SELECT @maxVal = ISNULL(max(codsequencia),0) from teste_sequencial
DBCC CHECKIDENT(teste_sequencial, RESEED, @maxVal)

Note, if u put the +1 after the 'ISNULL' part, the next identity column will jump +1, for example - current column 10 , after the code the next will be 11, if u use +1 after isnull , will be +12.

AND, the codes :

DBCC CHECKIDENT (teste_sequencial)

Exec sp_MSforeachtable 'DBCC CHECKIDENT(''?'')'

Didn't work for me at all in cases rollbacks cases. If u open a transaction , and do the rollback , the reseed will start at the last number used in the transaction.

Diogo Rocha
  • 9,759
  • 4
  • 48
  • 52
0

Adding to @010110110101's answer - to skip tables that don't have an identity column:

-- sets all the seeds to 1
exec sp_MSforeachtable @command1 = 'IF OBJECTPROPERTY(object_id(''?''), ''TableHasIdentity'') = 1 DBCC CHECKIDENT (''?'', RESEED, 1)'

-- run it again to get MSSQL to figure out the MAX/NEXT seed automatically
exec sp_MSforeachtable @command1 = 'IF OBJECTPROPERTY(object_id(''?''), ''TableHasIdentity'') = 1 DBCC CHECKIDENT (''?'')'
AndyMc
  • 377
  • 3
  • 6