1

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

无法将值 NULL 插入列“x”、表“表”;列不允许空值。插入失败。
该语句已终止。

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

我怎么解决这个问题?

4

1 回答 1

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;

结果:

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,句号。或者停止关心差距。

于 2013-10-25T19:25:29.717 回答