为什么IDENTITY列中存在空白?

时间:2013-10-25 19:17:45

标签: sql-server sql-server-2008 ssms auto-increment identity

如果我正确输入数据,我的表工作正常 - 我可以插入数据,IDENTITY值为1,2,3,4。但是,如果我犯了错误并收到错误信息,例如

  

无法将值NULL插入列'x',表'table';列不允许空值。 INSERT失败。
该声明已被终止。

然后,如果我成功插入另一行,则IDENTITY值为6,而不是5。

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:10)

嗯,首先:

这不是问题。

“问题”在很大程度上取决于设计。

不要,我再说一遍,不要指望IDENTITY列保持一组漂亮,连续的值,没有间隙。你真的不应该关心是否存在差距,但它们可能是各种各样的事情造成的。删除,回滚,failovers and service restarts等。不要担心价值并试图防止差距; IDENTITY可以高效地工作,因为SQL Server不会完成防止间隙所需的所有额外工作。如果你想这样做,你将不得不手动推出自己的解决方案。

哦,再播种不是一种选择。这就是原因。首先,我们举一个例子,表中没有主键(或者至少主键不在IDENTITY列上):

CREATE TABLE dbo.foo(id INT IDENTITY(1,1));
GO
INSERT dbo.foo DEFAULT VALUES;
GO 5
DBCC CHECKIDENT('dbo.foo', reseed, 0);
INSERT dbo.foo DEFAULT VALUES;
GO
SELECT id FROM dbo.foo ORDER BY id;
GO
DROP TABLE dbo.foo;

结果:

id
----
1
1 <-- oops! Duplicate. We probably didn't want that, right?
2
3
4
5

现在,如果IDENTITY列也是主键(非常常见):

CREATE TABLE dbo.foo(id INT IDENTITY(1,1) PRIMARY KEY);
GO
INSERT dbo.foo DEFAULT VALUES;
GO 5
DBCC CHECKIDENT('dbo.foo', reseed, 0);
GO
INSERT dbo.foo DEFAULT VALUES;
GO
DROP TABLE dbo.foo;

糟糕:

  

Ms 2627,Level 14,State 1,Line 7   
违反PRIMARY KEY约束'PK_ foo _3213E83FE3F1E24C'。无法在对象'dbo.foo'中插入重复键。重复键值为(1)。   该声明已经终止。

那你打算做什么呢?循环直到你不再获得异常?写出找到第一个间隙的各种复杂间隙和孤岛码,然后SET IDENTITY_INSERT ON;并手动插入值?为什么?你获得了什么?行军减速到20亿并且溢出?我不明白这种对序列号的迷恋以及IDENTITY列中没有间隙。这是一种代理,毫无意义的价值。让我再说一遍:

差距不是问题。

问题不在于技术。问题是首先担心差距。如果您关心差距,请不要试图弄清楚如何使用IDENTITY来阻止它们;只是停止使用IDENTITY,句号。或者停止关心差距。