52

我在 MySQL 5.5.24 版中有下表

DROP TABLE IF EXISTS `momento_distribution`;

CREATE TABLE IF NOT EXISTS `momento_distribution`
  (
     `momento_id`       INT(11) NOT NULL,
     `momento_idmember` INT(11) NOT NULL,
     `created_at`       DATETIME DEFAULT NULL,
     `updated_at`       DATETIME DEFAULT NULL,
     `unread`           TINYINT(1) DEFAULT '1',
     `accepted`         VARCHAR(10) NOT NULL DEFAULT 'pending',
     `ext_member`       VARCHAR(255) DEFAULT NULL,
     PRIMARY KEY (`momento_id`, `momento_idmember`),
     KEY `momento_distribution_FI_2` (`momento_idmember`),
     KEY `accepted` (`accepted`, `ext_member`)
  )
ENGINE=InnoDB
DEFAULT CHARSET=latin1;

它有大量数据与其他两个表具有多对一关系,其中ondelete=restrictonupdate=restrict

现在,我需要更改结构并在表中引入单独的主键,同时仍保留现有的关系和数据。为此,我执行了以下查询:

ALTER TABLE  `momento_distribution` ADD  `id` INT( 11 ) NOT NULL FIRST;
ALTER TABLE  `momento_distribution` DROP PRIMARY KEY , ADD PRIMARY KEY (  `id` );

不幸的是,我的第二个查询失败并出现以下错误:

1062 - 键 'PRIMARY' 的重复条目 '0'

有人可以指出这个问题吗?我想问题是现有的关系,但我不想丢失现有的关系或数据,它有几千行。有没有办法做到这一点而不会丢失数据?

编辑: 通过查看数据,我知道新创建的列中的值是“0”。由于重复记录(在新主键中),这可能不允许更改主键

我有超过 8,000 行,所以我无法手动更改它。有没有办法分配rowid给新的主键?

4

8 回答 8

66

您需要将主键指定为自增

CREATE TABLE `momento_distribution`
  (
     `momento_id`       INT(11) NOT NULL AUTO_INCREMENT,
     `momento_idmember` INT(11) NOT NULL,
     `created_at`       DATETIME DEFAULT NULL,
     `updated_at`       DATETIME DEFAULT NULL,
     `unread`           TINYINT(1) DEFAULT '1',
     `accepted`         VARCHAR(10) NOT NULL DEFAULT 'pending',
     `ext_member`       VARCHAR(255) DEFAULT NULL,
     PRIMARY KEY (`momento_id`, `momento_idmember`),
     KEY `momento_distribution_FI_2` (`momento_idmember`),
     KEY `accepted` (`accepted`, `ext_member`)
  )
ENGINE=InnoDB
DEFAULT CHARSET=latin1$$

关于下面的评论,怎么样:

ALTER TABLE `momento_distribution`
  CHANGE COLUMN `id` `id` INT(11) NOT NULL AUTO_INCREMENT,
  DROP PRIMARY KEY,
  ADD PRIMARY KEY (`id`);

PRIMARY KEY 是唯一索引,因此如果它包含重复项,则不能将该列指定为唯一索引,因此您可能需要完全创建一个新列

于 2012-08-29T14:04:21.467 回答
25

在 mysql 控制台中运行以下查询:

SHOW CREATE TABLE momento_distribution

检查看起来像这样的线

CONSTRAINT `momento_distribution_FK_1` FOREIGN KEY (`momento_id`) REFERENCES `momento` (`id`)

它可能会有所不同,我只是猜测它可能是什么。如果您在“momento_id”和“momento_idmember”上都有一个外键,您将获得两个外键名称。下一步是删除外键。运行以下查询:

ALTER TABLE momento_distribution DROP FOREIGN KEY momento_distribution_FK_1
ALTER TABLE momento_distribution DROP FOREIGN KEY momento_distribution_FK_2

请务必将外键名称更改为您从CREATE TABLE查询中获得的名称。现在您没有任何外键,因此您可以轻松删除主键。尝试以下操作:

ALTER TABLE  `momento_distribution` DROP PRIMARY KEY

添加所需的列,如下所示:

ALTER TABLE  `momento_distribution` ADD  `id` INT( 11 ) NOT NULL  PRIMARY KEY AUTO_INCREMENT FIRST

此查询还会添加数字,因此您无需依赖 @rowid。现在您需要将外键添加回前面的列。为此,首先制作这些索引:

ALTER TABLE  `momento_distribution` ADD INDEX (  `momento_id` )
ALTER TABLE  `momento_distribution` ADD INDEX (  `momento_idmember` )

现在添加外键。根据需要更改参考表/列:

ALTER TABLE  `momento_distribution` ADD FOREIGN KEY ( `momento_id`) REFERENCES  `momento` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT 
ALTER TABLE  `momento_distribution` ADD FOREIGN KEY ( `momento_idmember`) REFERENCES  `member` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT 

希望有帮助。如果您遇到任何错误,请使用参考表的结构和您获得的错误代码编辑问题。

于 2012-08-30T04:23:31.490 回答
14

检查您的主键字段是否设置为自动递增

于 2016-01-05T20:14:06.747 回答
8

这一步对我来说非常适合..你可以试试

  1. 添加索引
  2. 添加自动增量
  3. 添加主键

希望它也对你有用。祝你好运

于 2017-11-27T09:14:58.997 回答
6

将您的 PRIMARY KEY 设置为 AUTO_INCREMENT。

于 2018-11-09T03:23:29.053 回答
1

对我来说,我忘记将 AUTO_INCREMENT 添加到我的主字段并插入没有 id 的数据。

于 2019-09-25T11:15:18.633 回答
0

AUTO_INCREMENT设置为PRIMARY KEY

于 2019-09-26T08:33:26.240 回答
0

我遇到了这个错误,Used typeorm migrations Api,这个错误如上所述是由于id没有自动递增,所以如果你使用typeorm的Api迁移来写迁移,当你写你的id列时,用这个来设置 id 列。 { name: "id", type: "int auto_increment", isPrimary: true }

于 2021-09-03T08:56:58.480 回答