如果我正确输入数据,我的表可以正常工作 - 我可以插入数据并且 IDENTITY 值为 1、2、3、4。但是,如果我犯了错误并收到错误消息,例如
无法将值 NULL 插入列“x”、表“表”;列不允许空值。插入失败。
该语句已终止。
然后,如果我成功插入另一行,则 IDENTITY 值为 6,而不是 5。
我怎么解决这个问题?
如果我正确输入数据,我的表可以正常工作 - 我可以插入数据并且 IDENTITY 值为 1、2、3、4。但是,如果我犯了错误并收到错误消息,例如
无法将值 NULL 插入列“x”、表“表”;列不允许空值。插入失败。
该语句已终止。
然后,如果我成功插入另一行,则 IDENTITY 值为 6,而不是 5。
我怎么解决这个问题?
好吧,首先:
这不是问题。
“问题”是非常非常设计的。
不要,我再说一遍,不要指望 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;
结果:
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;
哎呀:
消息 2627,级别 14,状态 1,第 7 行
违反主键约束“PK_ foo _3213E83FE3F1E24C”。无法在对象“dbo.foo”中插入重复键。重复键值为 (1)。
该语句已终止。
那么你打算在那里做什么呢?循环直到不再出现异常?编写各种复杂的间隙和孤岛代码,找到第一个间隙,然后SET IDENTITY_INSERT ON;
手动插入值?为什么?你得到了什么?将进军速度放慢到 20 亿并溢出?我不理解这种对序列号的痴迷,并且在 IDENTITY 列中没有空白。这是一个替代的,毫无意义的价值。让我再重复一遍:
间隙不是问题。
问题不在于技术。问题首先是担心差距。如果您关心差距,请停止尝试找出如何使用 IDENTITY 来防止它们;停止使用 IDENTITY,句号。或者停止关心差距。