IDENT_CURRENT值高于max(id)

时间:2013-10-22 08:41:25

标签: sql-server-2008 transactions identity-column

错误: 将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列不是引用,就可以更容易重新设置?

2 个答案:

答案 0 :(得分:3)

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

同样,如果你实际插入了2147483647行但删除了ID大于6728550的所有行,你会发现同样的情况。

第三,某人可能已将该身份重新接种为2147483647。

因此,有很多方法可以达到这种情况。我们不可能知道它是如何产生的。


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

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

第一个设置下一个值用作2.第二个然后调用此部分:

  

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

答案 1 :(得分: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()