Question

Error: Arithmetic overflow error converting IDENTITY to data type int. Arithmetic overflow occurred.

Debugging:

id = my Identity column, datatype INT. Increment=1, Seed=1

select max(id) as max, min(id) as min from eventlogreport
    Result: 6728550 1

select count(*) from eventlogreport
    Result: 6728550

So far soo good. It looks like we have plenty of room for more rows. But inserting 600 000 more rows gives the overflow error. More debugging.

SELECT IDENT_CURRENT ('EventLogReport') AS Current_Identity;
    Result: 2147483647

Questions:

  1. How can the current identity value be so high when the table doesn't contain the same amount of rows, and there are no ids that has been skipped?
  2. How can I safely set the IDENT_CURRENT to the same number as max(id)? Or maybe it's easier to reseed, as long as the id columns isn't references?
Was it helpful?

Solution

Identity values don't participate in transactions - so if you've had a large number of attempted inserts (after all current rows were added) that have subsequently been rolled back, then IDENT_CURRENT can be much higher than the highest observed value in the table.

Similarly, if you'd actually inserted 2147483647 rows but then deleted all rows with an ID greater than 6728550, you'd observe the same situation.

Thirdly, someone may have reseeded the identity to be 2147483647.

So there are many ways you may have reached this situation. It's impossible for us to know how it came about.


To set the identity value to be appropriate for the next insert, use DBCC CHECKIDENT twice:

DBCC CHECKIDENT(Table,RESEED,1)
DBCC CHECKIDENT(Table,RESEED)

The first sets the next value to use as 2. The second then invokes this part:

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. See the 'Exceptions' section that follows.

OTHER TIPS

Ad.1 It's because identity is somewhat independent from the table. Transactions have no affect on identity, and errors too. If you try to insert some rows, and the insert fails, identity values are reserved for those rows anyway. The reason for this behaviour is that if you have two transactions doing inserts, and the first one would get rolled back, the second one don't have to worry about filling the gap that's left after first transaction.

Two examples to demonstrate the behaviour:

drop table _test
GO
create table _test(
    id int identity(1,1),
    x tinyint
)
GO

-- example 1 (insert error):

insert into _test(x)
select 1 as x union all 
select 2 union all 
select 256
GO

select * from _test
select ident_current('_test')
GO

-- example 2 (rollback):

begin tran

    insert into _test(x)
    select 1 as x union all 
    select 2

rollback tran


select * from _test
select ident_current('_test')
GO

Ad.2 Reseed the identity if you have to; you can't "change" IDENT_CURRENT().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top