【发布时间】:2010-10-20 11:28:24
【问题描述】:
对于特定表,我将 ID 字段设置为自动编号(增量)。如果我快速连续向该表添加 5 行,是否保证每行的 ID 都比上一个大?例如,如果一些较早的值已被删除,自动编号是否会从 1 重新开始?
【问题讨论】:
标签: ms-access auto-increment autonumber
对于特定表,我将 ID 字段设置为自动编号(增量)。如果我快速连续向该表添加 5 行,是否保证每行的 ID 都比上一个大?例如,如果一些较早的值已被删除,自动编号是否会从 1 重新开始?
【问题讨论】:
标签: ms-access auto-increment autonumber
我唯一遇到过 Access 自动编号问题的情况是,我错误地将自动编号键字段的值设置为低于使用附加查询的当前最大值的数字。记录删除在编号中造成了空白。 Access 允许您将一个值强制输入自动编号字段,有时(并非总是如此,我不知道为什么)自动编号会重置为较小的数字。最终,随着记录的添加,我遇到了“重复键”错误。除此之外,我多年来从未遇到过麻烦。
这个问题有几个关于增量值的答案。据我所知,Access自动编号字段只能设置为“增量”(按1)或“随机”,除了1之外没有其他方法可以设置数字增量。如果我对此有误,请指教我。
【讨论】:
遗憾的是,即使是 Microsoft 的应用程序也不是绝对可靠的。但这就是它的工作方式,我还没有看到它失败。也没有听说过它会因故意或意外颠覆而失败。
不过,不要指望它对每个整数值都有一行。除了删除的行之外,它还会用完失败的追加操作的数字。
【讨论】:
“如果删除某些记录并且压缩数据库,则下一个标识将重置为使用的最低数字 + 1”的语句不正确。 Access 97 中使用的 Jet 3.5 中发生了这种情况,而 Access 2000 中使用的 Jet 4.0 中则没有。
【讨论】:
David W. Fenton 写道:“Jet Autonumber 字段不是身份字段。它只是一个具有特殊默认值的长整数字段。该默认值可以是 INCREMENT 或 RANDOM,但因为它只是一个默认值,您可以将任何长整数值附加到该字段,只要它不违反索引。”
这有点混乱。 ACE/Jet SQL 语法有一个 IDENTITY 关键字(COUNTER、AUTOINCREMENT)但没有 AUTONUMBER 关键字。显然 ACE/Jet IDENTITY 是 IDENTITY!
但我想在这里解决的问题(评论太长)是关于它“只是一个具有特殊默认值的长整数字段”的错误陈述。
考虑一下这个 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_HASDFAULT 为 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 和不使用IDENTITY 关键字(或其同义词)创建自动增量列)。如果有人知道其中一种方法,请告诉我。
顺便说一句,上述错误消息表明我将“自动编号”作为访问术语是错误的。似乎在 ACE/Jet 引擎级别“自动编号”是 IDENTITY 的非关键字同义词(即自动增量风格自动编号),但不是其他自动编号风格的同义词。
【讨论】:
CREATE TABLE TestAuto (ID COUNTER UNIQUEIDENTIFIER NOT NULL, data_col INTEGER NOT NULL); 执行正常,但我最终得到一个递增列(如果你愿意的话,一个 IDENTITY 列);换句话说,UNIQUEIDENTIFIER 关键字被忽略。您可以在不使用DEFAULT 的情况下发布自动生成随机/guid 值的代码吗?很高兴看到。
我有一个以前在复制数据库中使用的表。有些自动编号是负数,有些非常大。这对于复制表来说是正常的,因此您无法确定自动编号是否会大于前一个数字,它可能是负数。
【讨论】:
Jet Autonumber 字段不是身份字段。它只是一个具有特殊默认值的长整数字段。该默认值可以是 INCREMENT 或 RANDOM,但由于它只是一个默认值,因此您可以将任何长整数值附加到该字段,只要它不违反索引即可。
递增的自动编号永远不会恢复为 1,除非您已删除所有记录并进行了压缩,或者在种子值损坏的情况下。后者在 Jet 4 的早期版本(Service Pack 6 之前)中经常发生,其中种子值会被重置,这会导致各种问题,包括损坏的 PK 索引。幸运的是,这个问题最终得到了解决,而且因为 Jet 是一个 Windows 组件,所以几乎没有任何计算机会安装 Jet 4 service pack 8。
正如 onedaywhen 所说,如果递增的自动编号超过长整数的最大正值,您可以获得负值,但这向我表明您的表中可能有足够的记录,您需要不同的数据库引擎,或者您'不正确地将您的表视为临时表(即追加和删除大量记录)。
正如其他人所说,唯一性不是由自动编号数据类型控制,而是由索引控制。如果您创建了非唯一索引,则可以附加重复值。我无法想象你为什么想要一个具有重复值的自动编号字段,但关键是如果你不添加唯一索引,你可以做到这一点。由于大部分 Autonumber 字段都用作代理主键,因此它们将具有唯一的 PK 索引,并且数据表将按 PK 顺序(聚集)写入。关于唯一性,如果您使用自动编号作为代理 PK,并且表中有任何应该唯一的自然键(并且 可以 是唯一的,即不允许 Nulls),您应该在自然键字段(单个字段或复合索引)上也有唯一索引。
【讨论】:
首先,您的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 等。
【讨论】:
我的答案是 3 串 VBA 代码!
Set db = CurrentDb
Set tbl = db.TableDefs("your_tbl")
Set current_index = tbl.Indexes.Item("PrimaryKey").DistinctCount
【讨论】:
DistinctCount 报告索引中不同键值的数量。所以一个有 2 行的表,自动编号主键 1 和 3,DistinctCount 会给你 2。这并不能说明下一个自动编号值是什么。
如果删除了一些记录并且压缩了数据库,则下一个标识将重置为使用的最低数字 + 1 - 如果表被清空,则在压缩后下一个标识将设置回 1。
【讨论】: