由于“错误形成的外键约束”错误,无法更改主键

时间:2015-07-15 06:39:39

标签: mysql sql

我有一个具有以下架构定义的表:

CREATE TABLE `currency` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `code` char(3) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL
  PRIMARY KEY (`id`),
  UNIQUE KEY `code_UNIQUE` (`code`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

我想要的是删除id列并将code作为新的主键。并且其他一些表具有此表的外键。我尝试了以下命令但失败了:

SET FOREIGN_KEY_CHECKS=0;
ALTER TABLE `currency` CHANGE COLUMN `id` `id` INT(11) NOT NULL, DROP PRIMARY KEY;
ALTER TABLE currency ADD PRIMARY KEY (code);
SET FOREIGN_KEY_CHECKS=1;

MySQL抛出以下异常:

  

[查询2中的错误]将“./db/#sql-849_1”重命名为“./db/currency”时出错(错误号:150 - 错误地形成了外键约束)       执行停止了!

3 个答案:

答案 0 :(得分:12)

错误

  

重命名时错误...错误号:150 - 外键约束形成错误)

发生是因为您尝试删除引用的主键,即使您使用SET FOREIGN_KEY_CHECKS=0;禁用外键约束检查

禁用外键检查将允许您临时删除currency表中的行或在外键表中添加无效的currencyId,但不能删除主键。

更改已被其他表引用的PRIMARY KEY并不简单,因为您可能会丢失表之间的参照完整性并丢失数据之间的关系。为了保存数据,您需要一个过程,例如:

  • 向每个FK表添加新的外键列(code
  • 通过更新
  • 映射上一个code的{​​{1}}外键
  • 删除现有外键
  • 删除旧的currencyId外键列
  • 删除所有FK后,更改currencyId表格上的主键
  • 根据新的currency
  • 重新建立外键

以下操作无需禁用code,但需要对引用FOREIGN_KEY_CHECKS的所有表重复执行外键映射/删除/重新创建步骤:

currency

SqlFiddle here

答案 1 :(得分:3)

正在运行

ALTER TABLE myTable DROP PRIMARY KEY;

导致错误,如

`Error Code: 1025. Error on rename of 'some_name' to 'another_name' (errno: 150 - Foreign key constraint is incorrectly formed)`
  

删除,创建新列并将其添加为主键 all   作为一个单一命令就像一个魅力。

即使我不知道根本原因,但这是我提出的最终解决方案:

-- Suppose c1 and c2 are a composite primary key and 
-- I want to add an incremental primary key named id
ALTER TABLE myTable 
    DROP PRIMARY KEY, 
    ADD id INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT FIRST, 
    ADD INDEX `an_index_name_for_c1_c2` (`c1`, `c2`);

请注意,为了遗留代码的性能,我将以前的复合主键列添加为新的复合索引。

答案 2 :(得分:0)

为什么不

  • 删除外键
  • 删除主键
  • 创建主键
  • 创建外键

我必须承认我现在(没有)的流量不多,只是测试了可以轻松恢复的数据,但这对我来说很好。