【问题标题】:Set AUTO_INCREMENT on a column with missing values在缺少值的列上设置 AUTO_INCREMENT
【发布时间】:2017-04-08 08:25:41
【问题描述】:

我的数据库中有一个名为users 的表。它有一个类型为int 的字段id。到目前为止,这是为每个注册的用户手动增加的,并且由于删除的用户帐户而丢失了一些中间值。我无法更改其他注册用户的用户名。我尝试使用此语句将此列更改为AUTO_INCREMENT

ALTER TABLE `userinfo` CHANGE `id` `id` BIGINT(20) NOT NULL AUTO_INCREMENT;

但我收到以下错误

1062 - ALTER TABLE 导致 auto_increment 重新排序,导致 键“P​​RIMARY”的重复条目“1”

我的表中只有大约 200 个用户。所以我想从201开始AUTO_INCREMENT。我执行了以下语句

ALTER TABLE `userinfo` AUTO_INCREMENT=201;
ALTER TABLE `userinfo` CHANGE `id` `id` INT(10) NOT NULL AUTO_INCREMENT;

但我仍然遇到同样的问题。

【问题讨论】:

  • 请在表格中填写您的最后一个id
  • @Barmar 如果列中没有缺失值我已经尝试过那里给出的内容,但它不起作用,则您所指问题的答案有效。我得到同样的错误。
  • @RaminDarvishov 最后一个 id 是 191
  • 您的ids 表中是否有重复的userinfo?。

标签: mysql database


【解决方案1】:

如果你没有重复 (id),你应该没有问题:

mysql> SELECT VERSION();
+-----------+
| VERSION() |
+-----------+
| 5.7.17    |
+-----------+
1 row in set (0.00 sec)

mysql> DROP TABLE IF EXISTS `userinfo`;
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE TABLE IF NOT EXISTS `userinfo` (
    ->   `id` INT(11) NOT NULL
    -> );
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO `userinfo`
    ->   (`id`)
    -> VALUES
    ->   (1),
    ->   (2),
    ->   (3),
    ->   -- (1),
    ->   (10),
    ->   (11),
    ->   (15),
    ->   (20),
    ->   (182),
    ->   (191);
Query OK, 9 rows affected (0.00 sec)
Records: 9  Duplicates: 0  Warnings: 0

mysql> ALTER TABLE `userinfo`
    ->   CHANGE `id` `id` BIGINT(20) NOT NULL
    ->   PRIMARY KEY AUTO_INCREMENT;
Query OK, 9 rows affected (0.00 sec)
Records: 9  Duplicates: 0  Warnings: 0

mysql> ALTER TABLE `userinfo` AUTO_INCREMENT = 201;
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> SHOW CREATE TABLE `userinfo`\G
*************************** 1. row ***************************
       Table: userinfo
Create Table: CREATE TABLE `userinfo` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=201 DEFAULT CHARSET=utf8mb4
1 row in set (0.00 sec)

另一种情况:

mysql> SELECT VERSION();
+-----------+
| VERSION() |
+-----------+
| 5.7.17    |
+-----------+
1 row in set (0.00 sec)

mysql> DROP TABLE IF EXISTS `userinfo`;
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE TABLE IF NOT EXISTS `userinfo` (
    ->   `id` INT(11) NOT NULL
    -> );
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO `userinfo`
    ->   (`id`)
    -> VALUES
    ->   (1),
    ->   (2),
    ->   (3),
    ->   (1), -- Duplicate
    ->   (10),
    ->   (11),
    ->   (15),
    ->   (20),
    ->   (182),
    ->   (191);
Query OK, 10 rows affected (0.00 sec)
Records: 10  Duplicates: 0  Warnings: 0

mysql> ALTER TABLE `userinfo`
    ->   CHANGE `id` `id` BIGINT(20) NOT NULL
    ->   PRIMARY KEY AUTO_INCREMENT;
ERROR 1062 (23000): ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '1' for key 'PRIMARY'

【讨论】:

  • 这在我的经验中是错误的(mysql 5.7.28)如果插入是批量插入语句,则当插入的值中有间隙时重新排序失败 - 不确定其余部分是否重要schema 更复杂,但我的经验似乎与这个例子相反。我想我已经找到了解决方案,请参阅我的答案。
  • @user6096790:我不完全理解你提到的问题。查看可能有用的完整示例dbfiddle
  • 就我而言,我试图从主键字段缺少顺序值的表中导入 mysqldump 数据。导入失败并出现上述错误,当然,源主键字段中没有重复项。因此,您的示例不符合我的经验,因为即使没有重复值,也会发生重新排序错误。基本上,我的经验不符合您的说法,即“如果您没有重复 (id),您应该没有问题”。
【解决方案2】:

尝试将列重置为主键,如下所示:

ALTER TABLE `userinfo` CHANGE `id` `id` INT(10) PRIMARY KEY AUTO_INCREMENT;

【讨论】:

    【解决方案3】:

    你可以直接删除 auto_increment 然后设置 auto_increment,不需要重新创建主键

    ALTER TABLE `userinfo` CHANGE `id` `id` int NOT NULL;
    ALTER TABLE `userinfo` AUTO_INCREMENT=9;
    ALTER TABLE `userinfo` CHANGE `id` `id` int NOT NULL AUTO_INCREMENT;
    

    【讨论】:

      【解决方案4】:

      我遇到了同样的问题/错误(MySql 5.7.28),批量插入缺少主键/auto_increment 值的数据 - 即使没有重复。我想保留主键并且还需要保留原始字段值,因为重新排序会导致系统中的数据完整性问题。

      我的解决方案是删除 auto_increment,然后删除主键,如上所述:

      ALTER TABLE `userinfo` CHANGE `id` `id` int NOT NULL;
      ALTER TABLE `userinfo` DROP PRIMARY KEY;
      

      然后运行我的批量插入语句而不会出现重新排序问题。

      然后使用以下步骤恢复主键和原始值:

      1. 重命名现在包含所需值的原始 PK/自动增量字段
      2. 使用原始字段名称创建新的 PK/自动增量字段
      3. 将自动递增值设置为比重命名字段的最大值大一
      4. 将原始值复制到新的 PK/自动增量字段中
      5. 删除重命名的字段(现在您拥有带有 PK/自动增量字段的原始架构,并根据需要在序列中具有原始间隙。

      这是前两步的sql:

      ALTER TABLE `userinfo` CHANGE `id` `orig_id` INT;
      ALTER TAble `userinfo` add id int auto_increment not null primary key;
      

      然后使用如下查询结果:

      select max(orig_id) + 1 from `userinfo`;
      

      在更新新的 PK/自动增量值之前设置新的自动增量:

      ALTER TABLE `userinfo` AUTO_INCREMENT=201;
      UPDATE `userinfo` set id = orig_id;
      ALTER TABLE `userinfo` drop column orig_id;
      

      现在我已经完全按照需要复制了原始表值。我希望这可以帮助其他人节省时间。

      【讨论】:

        猜你喜欢
        • 2018-11-24
        • 2020-11-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-22
        • 2019-06-20
        • 1970-01-01
        • 1970-01-01
        • 2019-05-23
        相关资源
        最近更新 更多