简体   繁体   English

为什么 MySQL 没有正确命名我的外键?

[英]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`);

DEMO 演示

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM