为什么我的身份列中有间隔?

23 浏览
0 Comments

为什么我的身份列中有间隔?

如果我正确输入数据,我的表格工作正常-我可以插入数据,并且IDENTITY值为1、2、3、4。然而,如果我犯了一个错误并收到一个错误信息,例如:

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

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

我该如何解决这个问题?

0
0 Comments

为什么我的ID列中会有间隔?

首先,这不是一个问题。这个“问题”是非常明确的设计。不要期望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 <-- 哎呀!重复了。我们可能不想要这个,对吧?

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;

出错了:

Violation of PRIMARY KEY constraint 'PK_foo_3213E83FE3F1E24C'. Cannot insert duplicate key in object 'dbo.foo'. The duplicate key value is (1).

The statement has been terminated.

那么你打算怎么做呢?循环直到不再出现异常?编写各种复杂的间隔和岛屿代码,找到第一个间隔,然后打开SET IDENTITY_INSERT ON;并手动插入值?为什么?你得到了什么?减缓到20亿和溢出的步伐?我不明白为什么对于IDENTITY列中的顺序号和没有间隔的困扰。这只是一个替代的、无意义的值。让我再重复一遍:

间隔不是一个问题。

问题不是技术,问题是对间隔的担心。如果你关心间隔,就别再试图使用IDENTITY来防止它们,干脆就不要使用IDENTITY,或者不再关心间隔。

我不同意重新种子标识列是一个问题。在大多数情况下,我们讨论的是具有不必要间隔的PK + IDENTITY列,有时是不可接受的。重新种子的解决方案值得考虑,如果做得正确。

110% 不同意 - 没有办法“正确地做到这一点”。请参见我的编辑。

那么,建立一个自己的序列号生成器,可以容忍事务故障。在任何并发环境中使用RESEED都是容易出错的。

0