0

I have a table which has a primary key ID column and is set to increment 1 for each new entry, a fairly standard configuration. This table is updated regularly with new records, and is archived once a month to an archive table and then truncated.

Under normal operation the next record to go into the table after truncation would be whatever the next ID value is, ensuring that there is no overlap in IDs between the archive table and the "live" table.

Due to unknown factors, somehow the ID column in the live table "reverted" back to an ID that has already been used. Because this database was designed poorly, now I've got some data integrity issues.

My solution to resolve the issue is to update the ID column for all records in the "live" table so there will be no overlap with the ID's that exist in the "archive" table. Once I update the IDs I will reseed the Identity column so that future records will also not overlap.

My question is not about reseeding the column (using DBCC -- I know how to do this) but about how to go about re-numbering the existing records with new ID values. Should I do this with a looped dynamic SQL query (delete record, insert record), or is there some SQL Server function I am unaware of that can automatically renumber the ID column?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
LegendaryDude
  • 562
  • 8
  • 23
  • 1
    Don't know why you need looping or dynamic SQL. `BEGIN TRANSACTION; DECLARE @i INT; SELECT @i = MAX(id) FROM dbo.table WITH (HOLDLOCK); INSERT dbo.table(othercols) SELECT othercols FROM dbo.table; DELETE dbo.table WHERE id <= @i; COMMIT TRANSACTION;` – Aaron Bertrand Jun 30 '15 at 20:19
  • This is the type of answer I was looking for, thanks! I know it didn't need dyn SQL necessarily, just couldn't think of a smart way of doing this. If you put this in an answer instead of a comment I will mark it 'accepted.' – LegendaryDude Jun 30 '15 at 20:41

2 Answers2

1

This looks to be a duplicate of this question - How to update Identity Column in SQL Server?

The upshot of the conversations on there is that it is possible to do this but not advisable - especially if there are any other tables that refer to this identifier value in foreign keys etc. Better to cycle through and recreate the records using a cursor or similar, as you mention in your question.

Community
  • 1
  • 1
0

Just a simple update with a CTE should do it. If you want the ID's to start at a certain place, that's what the offset is for in the comment.

with myCTE as (
 select row_number() over (order by auditDate) + 0 rn/*This is whatever you want the ID's to start at*/, * from testTable 
)
update myCTE set id= rn;

Here's the SQL fiddle (I used a really simple table from another example I had up, but it should be easy to see what's going on)

http://sqlfiddle.com/#!3/ef0b36/1

Philip Devine
  • 1,169
  • 5
  • 11