Access的自动编号(增量)是否保证增加?

时间:2009-04-20 02:08:07

标签: ms-access auto-increment autonumber

对于特定的表,我将我的ID字段设置为AutoNumber(Increment)。如果我快速连续向该表添加5行,每个都保证比上一个更大的ID吗?例如,如果某些早期值已被删除,自动编号是否会从1重新启动?

9 个答案:

答案 0 :(得分:3)

我唯一一次遇到Access自动编号问题的时候,我错误地使用追加查询将自动编号关键字段的值设置为低于当前最大值的数字。通过记录删除在编号中创建了差距。 Access允许您将值强制转换为自动编号字段,有时(并非总是如此,我不知道为什么)自动编号​​会重置为较低的数字。最后,随着记录的添加,我遇到了“重复密钥”错误。除此之外,我多年来从未遇到过麻烦。

这个问题有几个答案,谈论增量值。据我所知,Access自动编号字段只能设置为'递增'(按1)或'随机',并且没有办法设置除1以外的数字增量。如果我错了,请指教我

答案 1 :(得分:3)

可悲的是,即使是微软的应用也不是万无一失的。但这就是它的工作方式,我没有看到它失败;也没有听说过没有意外或意外的颠覆。

但是,不要指望它对每个整数值都有一行。除了已删除的行之外,它还会使用数字作为失败的追加操作。

答案 2 :(得分:2)

语句“如果某些记录被删除且数据库被压缩,则下一个标识被重置为最低使用数字+ 1”是不正确的。这发生在Access 97中使用的Jet 3.5中,而不是Access 2000中使用的Jet 4.0。

答案 3 :(得分:2)

David W. Fenton写道:“Jet Autonumber字段不是一个标识字段。它只是一个带有特殊默认值的长整数字段。该默认值可以是INCREMENT或RANDOM,但因为它只是一个默认值,只要不违反索引,就可以在字段中追加任何长整数值。“

这有点困惑。 ACE / Jet SQL语法具有IDENTITY关键字(COUNTERAUTOINCREMENT),但没有AUTONUMBER关键字。显然ACE / Jet IDENTITYIDENTITY

但是我想在这里解决的问题(评论太长)是关于它“只是一个具有特殊默认值的长整数字段”的错误陈述。

考虑这个ACE / Jet SQL DDL(ANSI-92查询模式语法):

CREATE TABLE Test2_IDENTITY
(
   ID_identity_1 IDENTITY NOT NULL, 
   ID_identity_2 IDENTITY NOT NULL, 
   data_column INTEGER
);

执行时,它失败并显示消息“不允许结果表具有多个自动编号字段”。很明显,除此之外还有一些“特殊默认值”。

IDENTITY关键字创建一个自动编号(为了缺少更好的术语),使用递增算法生成值。 IDENTITY不能用于创建具有随机算法或自动编号的GUID(复制ID)风格的自动编号。对于其他这些情况,您确实需要使用“特殊默认值”,例如

CREATE TABLE TestAutonumbers 
(
   ID_identity IDENTITY NOT NULL, 
   ID_random INTEGER DEFAULT GenUniqueID() NOT NULL, 
   ID_guid UNIQUEIDENTIFIER DEFAULT GenGUID() NOT NULL, 
   data_col INTEGER
);

如果您使用ADOX之类的技术来检查此表的属性(信息架构),您会发现只有使用IDENTITY关键字创建的列将Autoincrement属性设置为true,并且此列的COLUMN_HASDEFAULT为false且COLUMN_DEFAULT为空值。因此,如果IDENTITY列确实具有“特殊默认值”,则引擎不会说明。

IDENTITY不同,对于这些其他类型的自动编号,每个表限制没有明确的一个,例如这很好用:

CREATE TABLE Test2_Autonumbers
(
   ID_random_1 INTEGER DEFAULT GenUniqueID() NOT NULL, 
   ID_random_2 INTEGER DEFAULT GenUniqueID() NOT NULL, 
   ID_guid_1 UNIQUEIDENTIFIER DEFAULT GenGUID() NOT NULL, 
   ID_guid_2 UNIQUEIDENTIFIER DEFAULT GenGUID() NOT NULL, 
   data_col INTEGER
);

我不知道的是,是否存在相当于GenUniqueID()GenGUID()的“特殊默认值”,以使用DEFAULT创建自动增量列并且不使用{{ 1}}关键字(或其同义词)。如果有人知道这种或那种方式,请告诉我。

顺便说一下,上面提到的错误消息表明我认为“自动编号”是一个访问术语是错误的。似乎在ACE / Jet引擎级别'Autonumber'是IDENTITY的非关键字同义词(即自动增量风味自动编号),但不是其他风格的自动编号的同义词。

答案 4 :(得分:1)

首先,您的IDENTITY(访问中的自动编号)列必须是INTEGER(访问中的长整数),而不是UNIQUEIDENTIFIER(访问中的复制ID),必须使用增量算法与用于生成新值的随机算法相反,并假设您的种子和增量值分别都是默认值1,那么如果删除表中的所有行并压缩数据库,则应重新接种IDENITTY列在1.如果没有,那么您可能需要安装Jet服务包(http://support.microsoft.com/kb/287756)。

请注意,当下一个自动生成的值超出INTEGER(访问中的长整数)的最大正值时,它将“换行”到负INTEGER范围并继续循环通过正负范围,在必要时生成重复值(除非该列另外由唯一约束覆盖)。实际上,如果增量值足够大,则可以保证值在大于和小于先前自动生成的值之间交替,例如, (ACE / Jet ANSI-92查询模式语法):

CREATE TABLE Test 
(
   ID INTEGER IDENTITY (0, 2147483647), 
   data_col INTEGER NOT NULL UNIQUE
)
;
INSERT INTO Test (data_col) VALUES (1)
;
INSERT INTO Test (data_col) VALUES (2)
;
INSERT INTO Test (data_col) VALUES (3)
;
INSERT INTO Test (data_col) VALUES (4)
;
INSERT INTO Test (data_col) VALUES (5)
;
INSERT INTO Test (data_col) VALUES (6)
;
INSERT INTO Test (data_col) VALUES (7)
;
INSERT INTO Test (data_col) VALUES (8)
;

自动生成的值为0,2147483647,-2,2147483645,-4,2147483643,-6,2147483641等。

答案 5 :(得分:1)

我有一个以前在复制数据库中使用的表。一些自动编号是负的,有些非常大。这对于复制表来说是正常的,因此您无法确定自动编号是否大于之前的编号,它可能是负数。

答案 6 :(得分:1)

Jet Autonumber字段不是标识字段。它只是一个带有特殊默认值的长整数字段。该默认值可以是INCREMENT或RANDOM,但因为它只是一个默认值,所以只要不违反索引,就可以向字段追加任何长整数值。

递增的自动编号永远不会恢复为1,除非您删除了所有记录并进行了压缩,或者在种子值损坏的情况下。后者经常发生在Jet 4的早期版本(服务包6之前),其中种子值将被重置,这将导致各种问题,包括损坏的PK索引。幸运的是,最终得到修复,并且由于Jet是一个Windows组件,因此几乎没有任何计算机可以使用Jet 4 Service Pack 8。

正如oneday所说,如果递增的Autonumber超过长整数的最大正值,你可以得到负值,但这表明你可能在表中有足够的记录需要一个不同的数据库引擎,或者你'不正当地将您的表视为临时表(即附加和删除大量记录)。

正如其他人所说,唯一性不受自动编号数据类型的控制,而是受索引控制。如果您创建了非唯一索引,则可以附加重复值。我无法想象为什么你想要一个具有重复值的自动编号字段,但重点是如果你不添加唯一索引就可以这样做。由于大多数自动编号字段用作代理主键,因此它们将具有唯一的PK索引,并且数据表将以PK顺序(群集)写入。关于唯一性,如果您使用Autonumber作为代理PK并且表中的任何自然键应该是唯一的(并且可以是唯一的,即不允许Null),您应该在自然关键字段(单个字段或复合索引)上也有唯一索引。

答案 7 :(得分:1)

我的答案是3个VBA代码串!

Set db = CurrentDb
Set tbl = db.TableDefs("your_tbl")
Set current_index = tbl.Indexes.Item("PrimaryKey").DistinctCount

答案 8 :(得分:0)

如果某些记录被删除并且数据库被压缩,则下一个标识将被重置为最低使用数字+ 1 - 如果该表被清空,则在压缩后将下一个标识设置回1。