为什么IDENTITY列中存在空白?

Moh*_*eri 1 sql-server identity ssms auto-increment sql-server-2008

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

无法将值NULL插入列'x',表'table'; 列不允许空值.INSERT失败.
该语句已终止.

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

我怎么解决这个问题?

Aar*_*and 10

好吧,首先:

这不是问题.

"问题"非常非常依赖于设计.

我重复一遍,不要指望IDENTITY列保持一组漂亮,连续的值,没有间隙.你真的不应该关心是否存在差距,但它们可能是各种各样的事情造成的.删除,回滚,故障转移和服务重启等.不要担心价值并试图防止差距; 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;
Run Code Online (Sandbox Code Playgroud)

结果:

id
----
1
1 <-- oops! Duplicate. We probably didn't want that, right?
2
3
4
5
Run Code Online (Sandbox Code Playgroud)

现在,如果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;
Run Code Online (Sandbox Code Playgroud)

哎呀:

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

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

差距不是问题.

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

  • @Orzen 110%不同意 - 没有办法"做对了".请看我的编辑. (5认同)
  • **差距不是问题** - 应该大胆地立即引起注意,也许人们会更快更彻底地了解这一事实. (3认同)