[英]Why is MySQL not properly naming my foreign key?
Please consider the following SQL code that I run in MySQL 8.0.22 (in an InnoDB database):请考虑我在 MySQL 8.0.22(在 InnoDB 数据库中)中运行的以下 SQL 代码:
CREATE TABLE `person` (
`person_id` smallint unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(128) NOT NULL,
PRIMARY KEY (`person_id`)
);
CREATE TABLE `pet` (
`pet_id` smallint unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(128) NOT NULL,
PRIMARY KEY (`pet_id`)
);
ALTER TABLE `pet`
ADD COLUMN `owner_id` smallint unsigned;
ALTER TABLE `pet`
ADD CONSTRAINT `fk_pet_person`
FOREIGN KEY `idx_fk_pet_person` (`owner_id`)
REFERENCES `person` (`person_id`);
SHOW CREATE TABLE pet;
The output of SHOW CREATE TABLE pet
is: SHOW CREATE TABLE pet
的 output 是:
CREATE TABLE `pet` (
`pet_id` smallint unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(128) NOT NULL,
`owner_id` smallint unsigned DEFAULT NULL,
PRIMARY KEY (`pet_id`),
KEY `fk_pet_person` (`owner_id`),
CONSTRAINT `fk_pet_person` FOREIGN KEY (`owner_id`) REFERENCES `person` (`person_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
In the output above, why is the KEY named fk_pet_person
when I specified its name as idx_fk_pet_person
in my ALTER TABLE
command?在上面的
idx_fk_pet_person
中,我在ALTER TABLE
命令中将其名称指定为 idx_fk_pet_person 时,为什么 KEY 名为fk_pet_person
? How can I get it to be named so?我怎样才能让它如此命名?
You are confusing the FOREIGN KEY and the INDEX that makes it work.您混淆了 FOREIGN KEY 和使其工作的 INDEX。 Pay attention - there is NO expression name (which looks like an index definition but is not) in the constraint definition displayed in your code.
请注意 - 代码中显示的约束定义中没有表达式名称(看起来像索引定义但不是)。
When there is no suitable index for the constraint to work, then this index is auto-created, and the constraint name is used as the index name.当没有合适的索引让约束起作用时,则自动创建该索引,并将约束名称用作索引名称。 If a suitable index exists, then auto-creation does not occur.
如果存在合适的索引,则不会发生自动创建。
If you want the index to have a defined name then you must create this index in a separate ALTER TABLE
(sub)statement before the constraint creation:如果您希望索引具有定义的名称,则必须在创建约束之前在单独的
ALTER TABLE
(子) 语句中创建此索引:
ALTER TABLE `pet`
ADD KEY `idx_fk_pet_person` (`owner_id`),
ADD CONSTRAINT `fk_pet_person`
FOREIGN KEY (`owner_id`)
REFERENCES `person` (`person_id`);
or或者
ALTER TABLE `pet`
ADD KEY `idx_fk_pet_person` (`owner_id`);
ALTER TABLE `pet`
ADD CONSTRAINT `fk_pet_person`
FOREIGN KEY (`owner_id`)
REFERENCES `person` (`person_id`);
MySQL documentation specifies this syntax for creating a foreign key: MySQL 文档指定了创建外键的语法:
[CONSTRAINT [symbol]] FOREIGN KEY
[index_name] (col_name, ...)
REFERENCES tbl_name (col_name,...)
[ON DELETE reference_option]
[ON UPDATE reference_option]
reference_option:
RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT
There are two reasons why my code does not set the [index_name]
and instead the index name is automatically made the same as the constraint name.我的代码没有设置
[index_name]
的原因有两个,而是索引名称自动与约束名称相同。 Both are evident from this paragraph taken from the MySQL 8.0 Reference Manual, section 13.1.20.5 FOREIGN KEY Constraints :从 MySQL 8.0 参考手册第13.1.20.5 节外键约束的这段中可以看出两者:
Prior to MySQL 8.0.16, if the CONSTRAINT symbol clause was not defined, or a symbol was not included following the CONSTRAINT keyword, both InnoDB and NDB storage engines would use the FOREIGN_KEY index_name if defined.
在 MySQL 8.0.16 之前,如果未定义 CONSTRAINT 符号子句,或者未在 CONSTRAINT 关键字之后包含符号,则 InnoDB 和 NDB 存储引擎都将使用 FOREIGN_KEY index_name(如果已定义)。 In MySQL 8.0.16 and higher, the FOREIGN_KEY index_name is ignored.
在 MySQL 8.0.16 及更高版本中,忽略 FOREIGN_KEY index_name。
The first reason is that I am running the code in MySQL 8.0.22.第一个原因是我在 MySQL 8.0.22 中运行代码。
The second reason is that I should have omitted the constraint name.第二个原因是我应该省略约束名称。
The workarounds in @akina's answer indeed enable me to specify a name for the foreign key (index) that is different from the constraint's name. @akina 的答案中的解决方法确实使我能够为与约束名称不同的外键(索引)指定一个名称。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.