0

错误: 将 IDENTITY 转换为数据类型 int 的算术溢出错误。发生算术溢出。

调试:

id = 我的身份列,数据类型 INT。增量=1,种子=1

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

select count(*) from eventlogreport
    Result: 6728550

到目前为止太好了。看起来我们有足够的空间容纳更多行。但是再插入 600 000 行会导致溢出错误。更多调试。

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

问题:

  1. 当表不包含相同数量的行,并且没有被跳过的 id 时,当前的标识值怎么会这么高?
  2. 如何安全地将 IDENT_CURRENT 设置为与 max(id) 相同的数字?或者,只要 id 列不是引用,重新播种可能更容易?
4

2 回答 2

3

标识值不参与事务 - 因此,如果您有大量尝试插入(在添加所有当前行之后)随后被回滚,则IDENT_CURRENT可能远高于表中观察到的最高值。

同样,如果您实际插入了 2147483647 行,但随后删除了所有ID大于 6728550 的行,您将观察到相同的情况。

第三,可能有人将身份重新设置为 2147483647。

所以有很多方法你可能会遇到这种情况。我们不可能知道它是如何产生的。


要将标识值设置为适合下一次插入,请使用DBCC CHECKIDENT两次:

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

第一个将下一个值设置为 2。第二个然后调用此部分:

如果表的当前标识值小于标识列中存储的最大标识值,则使用标识列中的最大值对其进行重置。请参阅下面的“例外”部分。

于 2013-10-22T10:35:14.353 回答
0

Ad.1 这是因为identity有点独立于表格。事务对身份没有影响,错误也没有。如果您尝试插入一些行,但插入失败,则无论如何都会为这些行保留标识值。这种行为的原因是,如果您有两个事务进行插入,并且第一个事务会回滚,那么第二个事务不必担心填充第一个事务后留下的间隙。

演示该行为的两个示例:

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 必要时重新植入身份;你不能“改变” IDENT_CURRENT()

于 2013-10-22T10:32:23.200 回答