代码之家  ›  专栏  ›  技术社区  ›  Smashery

访问的自动编号(递增)是否保证递增?

  •  1
  • Smashery  · 技术社区  · 15 年前

    对于一个特定的表,我将ID字段设置为自动编号(递增)。如果我快速连续地向这个表中添加5行,是否保证每个行的ID都大于最后一行?例如,如果删除了一些较早的值,自动编号是否从1重新开始?

    9 回复  |  直到 13 年前
        1
  •  3
  •   dsteele    15 年前

    唯一一次我在访问自动编号方面遇到困难是,在错误的情况下,我使用附加查询将自动编号键字段的值设置为低于当前最大值的数字。通过删除记录在编号中创建了间隙。访问允许您将值强制输入自动编号字段,有时(不总是,我不知道为什么),自动编号会重置为较低的数字。最后,在添加记录时,我遇到了“重复键”错误。除此之外,我多年来从未遇到过麻烦。

    这个问题有两个答案,讨论一个增量值。据我所知,访问自动编号字段只能设置为“增量”(1)或“随机”,并且不能设置除1以外的数字增量。如果我错了,请开导我。

        2
  •  3
  •   dkretz    15 年前

    遗憾的是,即使是微软的应用程序也并非一无是处。但这就是它的工作方式,我没有看到它失败,也没有听说它失败,除非是有意或偶然的颠覆。

    不过,不要期望每个整数值都有一行。除了删除的行之外,它还将使用最多的数字来执行失败的追加操作。

        3
  •  2
  •   Tony Toews    15 年前

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

        4
  •  2
  •   onedaywhen    15 年前

    大卫·W·芬顿写道:“喷气机自动编号字段不是一个标识字段。它只是一个带有特殊默认值的长整型字段。该默认值可以是递增的,也可以是随机的,但是由于它只是一个默认值,所以只要不违反索引,就可以将任何长整数值追加到字段中。”

    这有点困惑。ace/jet-sql语法具有 IDENTITY 关键字(关键字) COUNTER , AUTOINCREMENT )但没有自动编号关键字。显然是一架飞机 身份 是一个 身份 !

    但我想在这里说明的是(对注释来说太长了)它是“只有一个具有特殊默认值的长整型字段”的错误陈述。

    考虑这个ace/jetsqddl(ansi-92查询模式语法):

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

    执行时失败,并显示消息“结果表不允许有多个自动编号字段”。很明显,这里除了一个“特殊的默认值”之外还有其他的东西。

    这个 身份 关键字是使用递增算法创建一个自动编号(为了获得更好的术语)来生成值。 身份 不能使用随机算法或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,并且此列的列_HasDefault为false,列_Default为空。因此,如果一个标识列确实有一个“特殊默认值”,那么引擎就不会告诉你。

    不像 身份 对于这些其他类型的自动编号,每个表都没有明确的限制,例如,这很好:

    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 而且不使用 身份 关键字(或其同义词)。如果有人知道其中一种方法,请告诉我。

    顺便说一句,上面提到的错误消息表明“自动编号”是一个访问术语是错误的。似乎在ace/jet引擎级别,“autonumber”是非关键字的同义词 身份 (即自动增加风味自动编号),但不是其他风味自动编号的同义词。

        5
  •  1
  •   Fionnuala    15 年前

    我有一个以前在复制数据库中使用的表。有些自动编号是负数,有些则很大。对于复制的表,这是正常的,因此不能确定自动编号将大于前一个数字,它可能是负数。

        6
  •  1
  •   David-W-Fenton    15 年前

    jet autonumber字段不是标识字段。它只是一个带有特殊默认值的长整型字段。该默认值可以是递增的,也可以是随机的,但是由于它只是一个默认值,所以只要不违反索引,就可以将任何长整数值追加到字段中。

    递增的自动编号永远不会恢复为1,除非您已删除所有记录并压缩,或者在种子值损坏的情况下。后者在早期版本的jet 4(ServicePack6之前)中经常发生,在这里种子值将被重置,这将导致各种各样的问题,包括损坏的pk索引。幸运的是,这个问题最终得到了解决,而且由于Jet是一个Windows组件,所以几乎没有一台计算机能拥有比Jet4 Service Pack 8更高的版本。

    正如前一天所说,如果递增的自动编号超过了长整型的最大正值,则可以得到负值,但这将指示您的表中可能有足够的记录,需要不同的数据库引擎,或者您不正确地将表视为临时表(即,追加和删除大的记录数量)。

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

        7
  •  1
  •   onedaywhen    15 年前

    首先,你的 IDENTITY (访问中的自动编号)列必须是 INTEGER (访问中的长整数)与 UNIQUEIDENTIFIER (access中的replication id),必须使用增量算法,而不是随机算法来生成新值,并假定种子值和增量值分别为默认值1,然后如果删除表中的所有行并压缩数据库,则 IDENITTY 列应在1处重新种子。如果没有,则可能需要安装Jet Service Pack( http://support.microsoft.com/kb/287756 )

    注意当最大正值为 整数 (访问中的长整数)将被下一个自动生成的值超过,然后它将“包装”为负数 整数 范围,并将继续在正范围和负范围内循环,必要时生成重复值(除非列另外被唯一约束覆盖)。实际上,如果增量值足够大,则可以确保这些值在大于和小于以前自动生成的值之间交替,例如(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等。

        8
  •  1
  •   Anton.    13 年前

    我的答案是3串VBA代码!

    Set db = CurrentDb
    Set tbl = db.TableDefs("your_tbl")
    Set current_index = tbl.Indexes.Item("PrimaryKey").DistinctCount
    
        9
  •  0
  •   DJ.    15 年前

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