向现有外键添加唯一性
adding unique to existing foreign key
我有这个table
CREATE TABLE IF NOT EXISTS `transaction` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`amount` bigint(20) NOT NULL,
`req_id` int(11) NOT NULL,
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `transactions_873a2484` (`req_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_persian_ci AUTO_INCREMENT=914 ;
我想将此外键 transactions_873a2484
更改为唯一的外键
基本上我想把它改成
UNIQUE KEY `transactions_req_id_de2b5683_uniq` (`req_id`),
我的 table 中已经有很多数据,否则我会重新制作这个 table .... 有没有办法在不损害数据的情况下做到这一点?
我会不断改进的。 MySQL会尊重你的意愿,甚至让你搬起石头砸自己的脚:
create table t9
(
id int auto_increment primary key,
thing varchar(20) not null,
key(thing),
unique key (thing),
unique key `yet_another` (thing)
);
-- warning 1831 dupe index
show create table t9;
CREATE TABLE `t9` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`thing` varchar(20) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `thing_2` (`thing`),
UNIQUE KEY `yet_another` (`thing`),
KEY `thing` (`thing`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
所以看看你的 upsert 必须携带的所有行李(阅读:缓慢的额外不必要的索引)。
因此,如果您希望它尽可能精简,正如我在评论中提到的那样,首先通过在子表中删除 FK 来展开操作,首先是 referencing。参见 This Answer。
然后删除当前的非唯一父键:
DROP INDEX index_name ON tbl_name;
然后在父项中添加唯一键。这是新的 referenced:
CREATE UNIQUE INDEX idxName ON tbl_name (colName);
然后在子项中添加 FK(引用)
CREATE INDEX idxName ON child_tbl_name (colName);
您可以通过show create table theTableName
或SHOW INDEX
获取键名。给新的用新的名字,没关系。
如:
mysql> show index from t9;
+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| t9 | 0 | PRIMARY | 1 | id | A | 0 | NULL | NULL | | BTREE | | |
| t9 | 0 | thing_2 | 1 | thing | A | 0 | NULL | NULL | | BTREE | | |
| t9 | 0 | yet_another | 1 | thing | A | 0 | NULL | NULL | | BTREE | | |
| t9 | 1 | thing | 1 | thing | A | 0 | NULL | NULL | | BTREE | | |
+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
ALTER TABLE `transaction`
DROP INDEX `transactions_873a2484`,
ADD UNIQUE(req_id);
你不能把一个非唯一的变成UNIQUE
,但是上面的应该是等效的。数据不会受到伤害。
我有这个table
CREATE TABLE IF NOT EXISTS `transaction` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`amount` bigint(20) NOT NULL,
`req_id` int(11) NOT NULL,
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `transactions_873a2484` (`req_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_persian_ci AUTO_INCREMENT=914 ;
我想将此外键 transactions_873a2484
更改为唯一的外键
基本上我想把它改成
UNIQUE KEY `transactions_req_id_de2b5683_uniq` (`req_id`),
我的 table 中已经有很多数据,否则我会重新制作这个 table .... 有没有办法在不损害数据的情况下做到这一点?
我会不断改进的。 MySQL会尊重你的意愿,甚至让你搬起石头砸自己的脚:
create table t9
(
id int auto_increment primary key,
thing varchar(20) not null,
key(thing),
unique key (thing),
unique key `yet_another` (thing)
);
-- warning 1831 dupe index
show create table t9;
CREATE TABLE `t9` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`thing` varchar(20) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `thing_2` (`thing`),
UNIQUE KEY `yet_another` (`thing`),
KEY `thing` (`thing`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
所以看看你的 upsert 必须携带的所有行李(阅读:缓慢的额外不必要的索引)。
因此,如果您希望它尽可能精简,正如我在评论中提到的那样,首先通过在子表中删除 FK 来展开操作,首先是 referencing。参见 This Answer。
然后删除当前的非唯一父键:
DROP INDEX index_name ON tbl_name;
然后在父项中添加唯一键。这是新的 referenced:
CREATE UNIQUE INDEX idxName ON tbl_name (colName);
然后在子项中添加 FK(引用)
CREATE INDEX idxName ON child_tbl_name (colName);
您可以通过show create table theTableName
或SHOW INDEX
获取键名。给新的用新的名字,没关系。
如:
mysql> show index from t9;
+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| t9 | 0 | PRIMARY | 1 | id | A | 0 | NULL | NULL | | BTREE | | |
| t9 | 0 | thing_2 | 1 | thing | A | 0 | NULL | NULL | | BTREE | | |
| t9 | 0 | yet_another | 1 | thing | A | 0 | NULL | NULL | | BTREE | | |
| t9 | 1 | thing | 1 | thing | A | 0 | NULL | NULL | | BTREE | | |
+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
ALTER TABLE `transaction`
DROP INDEX `transactions_873a2484`,
ADD UNIQUE(req_id);
你不能把一个非唯一的变成UNIQUE
,但是上面的应该是等效的。数据不会受到伤害。