在存在外键约束时更改MySQL主键 [英] Changing MySQL primary key when foreign key contraints exist

查看:224
本文介绍了在存在外键约束时更改MySQL主键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个已经存在的表格(部分)大致如下:

I have two already-existing tables which look (in part) roughly like this:

CREATE TABLE parent (
    old_pk CHAR(8) NOT NULL PRIMARY KEY
) ENGINE=InnoDB;

CREATE TABLE child (
    parent_key CHAR(8),
    FOREIGN KEY (parent_key) REFERENCES parent(old_pk)
        ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB;

我要添加一个新的自动递增整数 id 列到 parent 并将其用作主键,同时仍保留 old_pk 作为唯一键,允许其他表(如 child )在外键约束中引用它。不幸的是,简单地说 ALTER TABLE parent DROP PRIMARY KEY 不起作用:

I want to add a new auto-incrementing integer id column to parent and use it as the primary key instead, while still keeping old_pk as a unique key and allowing other tables like child to reference it in foreign key contraints. Unfortunately, simply saying ALTER TABLE parent DROP PRIMARY KEY doesn't work:


错误代码:1025

Error Code : 1025

重命名'./data/#sql-4013_70f5e'至'./data/parent'(errno:150)时出错

Error on rename of './data/#sql-4013_70f5e' to './data/parent' (errno: 150)

一些googling表明这是由于 child 的现有外键引用。实质上,我需要一种方式告诉MySQL使用这个其他列作为主键,但不要忘记原始的唯一键的关键。有什么办法可以实现这一点,除了只是从中删除​​关键约束,然后重新启动它们?

Some googling suggests that this is due to the existing foreign key reference from child. In essence, I need a way to tell MySQL "use this other column as the primary key, but don't forget the unique-key-ness of the original one". Is there any way to accomplish this, other than just dropping the key constraints from child and reinstating them afterwards?

假设我必须改变表的位置,而不是创建具有相同数据的副本,并在以后交换它们。我在尝试改变表之前尝试使用 SET FOREIGN_KEY_CHECKS = 0 ,但它似乎不起作用。

Assume that I must alter the tables in place, rather than creating copies with the same data and swapping them in later. I've tried using SET FOREIGN_KEY_CHECKS = 0 before altering the table, but it does not seem to help.

推荐答案

在删除主键之前向old_pk添加一个索引(甚至可以是UNIQUE):

Add an index (it could even be UNIQUE) to old_pk before dropping the primary key:

mysql> CREATE TABLE parent (
    ->     old_pk CHAR(8) NOT NULL PRIMARY KEY
    -> ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE child (
    ->     parent_key CHAR(8),
    ->     FOREIGN KEY (parent_key) REFERENCES parent(old_pk)
    ->         ON UPDATE CASCADE ON DELETE CASCADE
    -> ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO parent VALUES ('a');
Query OK, 1 row affected (0.01 sec)

mysql> CREATE INDEX old_pk_unique ON parent (old_pk);
Query OK, 1 row affected (0.01 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> ALTER TABLE parent DROP PRIMARY KEY;
Query OK, 1 row affected (0.01 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> INSERT INTO child VALUES ('a');
Query OK, 1 row affected (0.00 sec)

mysql> SHOW CREATE TABLE parent;
+--------+------------------------------------------------------------------------------------------------------------------------------+
| Table  | Create Table                                                                                                                 |
+--------+------------------------------------------------------------------------------------------------------------------------------+
| parent | CREATE TABLE `parent` (
  `old_pk` char(8) NOT NULL,
  KEY `old_pk_unique` (`old_pk`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+--------+------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> INSERT INTO child VALUES ('b');
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test/child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_key`) REFERENCES `parent` (`old_pk`) ON DELETE CASCADE ON UPDATE CASCADE)

mysql> INSERT INTO parent VALUES ('b');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO child VALUES ('b');
Query OK, 1 row affected (0.01 sec)

mysql> ALTER TABLE parent ADD id INT;
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> UPDATE parent SET id = 1 WHERE old_pk = 'a';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> UPDATE parent SET id = 2 WHERE old_pk = 'b';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> ALTER TABLE parent ADD PRIMARY KEY (id);
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> SHOW CREATE TABLE parent;
+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table  | Create Table                                                                                                                                                                             |
+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| parent | CREATE TABLE `parent` (
  `old_pk` char(8) NOT NULL,
  `id` int(11) NOT NULL default '0',
  PRIMARY KEY  (`id`),
  KEY `old_pk_unique` (`old_pk`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

这篇关于在存在外键约束时更改MySQL主键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆