更新外键以指向不同表的最佳方法是?

时间:2018-01-09 21:36:50

标签: mysql foreign-keys

我正在清理一个随着时间的推移而变得混乱的mysql数据库。清理是增量的(也就是说我不想一次迁移所有表)。

我希望尽可能避免对旧表进行破坏性编辑。例如,我将表文件夹重命名为 decomissioned_folders ,然后创建一个新的文件夹表,可以将相应的记录迁移到该表中,而不会影响旧表。

此数据库中有很多表,其中一个是表用户。数据库中的许多其他表具有指向表用户的外键。

我想知道:

如果我将表用户重命名为 decomissioned_users ,然后创建一个新的用户表并填充它,那么最好的处理方法是什么用外键?对于数据库中现在包含指向旧 decomissioned_users 表的外键的每个表,是否有(简单)方法更新这些外键以指向新的用户表而不是?

(注意,id的值在表之间不会改变,因此外键的值将在表之间保持有效。)

1 个答案:

答案 0 :(得分:2)

有一种简单的方法,但它涉及丢弃旧的外键并创建新的外键。

这是一个演示:

mysql> create table foo (id serial primary key);

mysql> create table bar (foo_id bigint unsigned, foreign key (foo_id) references foo(id));

重命名表后,外键引用会自动更新,以跟随重命名的表:

mysql> rename table foo to old_foo;

mysql> show create table bar\G
*************************** 1. row ***************************
       Table: bar
Create Table: CREATE TABLE `bar` (
  `foo_id` bigint(20) unsigned DEFAULT NULL,
  KEY `foo_id` (`foo_id`),
  CONSTRAINT `bar_ibfk_1` FOREIGN KEY (`foo_id`) REFERENCES `old_foo` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

创建新表后:

mysql> create table foo like old_foo;

我们可以通过以下方式重新定义外键:

mysql> alter table bar 
       drop foreign key bar_ibfk_1, 
       add foreign key (foo_id) references foo(id);

现在该表引用了新表:

mysql> show create table bar\G
*************************** 1. row ***************************
       Table: bar
Create Table: CREATE TABLE `bar` (
  `foo_id` bigint(20) unsigned DEFAULT NULL,
  KEY `foo_id` (`foo_id`),
  CONSTRAINT `bar_ibfk_2` FOREIGN KEY (`foo_id`) REFERENCES `foo` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

如果您有许多外键,可以通过查询INFORMATION_SCHEMA,表TABLE_CONSTRAINTS和KEY_COLUMN_USAGE来发现它们的列表。通过此元数据,您可以构建ALTER TABLE语句以更改外键。