在MySQL中重命名外键列

51

我们试图在MySQL(5.1.31,InnoDB)中重命名一个作为外键连接到另一张表的列。

起初,我们尝试使用Django-South,但遇到了已知问题:

http://south.aeracode.org/ticket/243

OperationalError: (1025, "Error on rename of './xxx/#sql-bf_4d' to './xxx/cave_event' (errno: 150)")

Error on rename of './xxx/#sql-bf_4b' to './xxx/cave_event' (errno: 150)

这个错误150肯定与外键约束有关。例如,参见:

What does mysql error 1025 (HY000): Error on rename of './foo' (errorno: 150) mean?

http://www.xaprb.com/blog/2006/08/22/mysqls-error-1025-explained/

所以,现在我们正在尝试使用原生SQL进行重命名。看起来我们需要先删除外键,然后进行重命名,最后再添加外键。这听起来正确吗?是否有更好的方法,因为这似乎相当混乱和繁琐?

如果您能提供任何帮助,将不胜感激!


可能是如何在MySQL中重命名外键?的重复问题。 - Ben
7个回答

61
据我所知,删除约束、重命名、再添加约束是唯一的方法。首先备份!

11
自 MySQL 5.6.6 版本开始,重命名列时所有外键将自动更新。http://dev.mysql.com/doc/refman/5.6/en/alter-table.html - BenL
4
@BenL 这不是完全正确的。页面上写着:“在MySQL 5.6.6之前,在同一ALTER TABLE语句中添加和删除外键可能在某些情况下存在问题,因此不支持这样做。应该为每个操作使用单独的语句。从MySQL 5.6.6开始,对于ALTER TABLE ... ALGORITHM=INPLACE,可以在同一ALTER TABLE语句中添加和删除外键,但仍不支持ALTER TABLE ... ALGORITHM=COPY。”另外,我亲眼看到MySQL 5.6.2更改了FK中的列名。但是在MySQL 5.0.94中目前(还)不可能实现。 - hypercube

29

如果有人在寻找语法,它的写法大致是这样的:

alter table customer_account drop foreign key `FK3FEDF2CC1CD51BAF`; 

alter table customer_account  add constraint `FK3FEDF2CCD115CB1A` foreign key (campaign_id) REFERENCES campaign(id);

3
这里是常规键的SQL语法。
ALTER TABLE `thetable`
  DROP KEY `oldkey`, 
  ADD KEY `newkey` (`tablefield`);

1

在@Dewey的回答基础上,这里有一个小脚本,可以以有用的方式重命名Hibernate生成的FK(外键)(“FK__”+表名+“__”+引用表名)

SELECT CONCAT(
  "alter table ", TABLE_NAME, " drop foreign key ", CONSTRAINT_NAME,";\n",
  "alter table ", TABLE_NAME, " drop key ", CONSTRAINT_NAME, ";\n",
  "alter table ", TABLE_NAME, " add key FK__", table_name, "__",
      referenced_table_name, " (", column_name, ");\n",
  "alter table ", TABLE_NAME, " add constraint FK__", table_name, "__",
      referenced_table_name , " foreign key (", column_name, ") ",
      "references ", referenced_table_name,
      "(", referenced_column_name, ");"
  ) AS runMe 
FROM
  information_schema.key_column_usage
WHERE 
  TABLE_SCHEMA='myschemaname' 
  AND 
  constraint_name like 'FK_%';

一些输出:

alter table visitor_browsers drop foreign key FK_4ygermmic4fujggq1kp96dx47;
alter table visitor_browsers drop key FK_4ygermmic4fujggq1kp96dx47;
alter table visitor_browsers add key FK__visitor_browsers__websites (website);
alter table visitor_browsers add constraint FK__visitor_browsers__websites foreign key (website) references websites(id);

0
以下查询将自动构建正确的语法。 只需执行返回的每行,所有FKEYs都将消失。
我把反向操作(添加它们回来)留给你作为练习。
SELECT CONCAT("alter table ", TABLE_NAME," drop foreign key `", CONSTRAINT_NAME,"`; ") AS runMe
FROM information_schema.key_column_usage 
WHERE TABLE_SCHEMA='MY_SCHEMA_NAME';

0

03 2022

我知道这个问题很旧了,但如果有人正在寻找带有解释的答案,那么这里就是。下面的代码已经经过测试。

  1. 首先删除旧的约束 OldColumnConstrain
  2. 然后删除旧的外键列 OldColumnName
  3. 添加新的外键列 NewColumnName,数据类型为 INTEGER UNSIGNED NULL
  4. (可选) 我想在特定列之后添加这个新的外键 - AFTER previousColumn
  5. 将新列 newColumnConstrain 约束到参考表 t1
ALTER TABLE t1
DROP FOREIGN KEY OldColumnConstrain,
DROP COLUMN OldColumnName,
ADD NewColumnName INTEGER UNSIGNED NULL AFTER previousColumn,
ADD CONSTRAINT newColumnConstrain FOREIGN KEY (NewColumnName) REFERENCES t2(id);

重要

运行上述查询将重命名您的Old列为New列(不完全是重命名,而是删除和添加列),但请注意,该列数据将丢失,并将被替换为 NULL

你真的能重命名你的fk吗?

我想不行。如果我找到解决方案,我会更新这个答案。
请参阅此答案 https://dev59.com/KHI-5IYBdhLWcg3wF0Yc#2014519


-2
如果您使用GUI工具,这项任务会变得更简单。我尝试使用IntelliJ IDEA 数据库工具 重命名ID列,它非常顺利!在重命名表或列时,我不必担心外键的问题。
请参阅IntelliJ IDEA帮助|重命名项目以获取更多详细信息。

MySQL 5.7


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接