繁体   English   中英

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

[英]Why is MySQL not properly naming my foreign key?

请考虑我在 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;

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

在上面的idx_fk_pet_person中,我在ALTER TABLE命令中将其名称指定为 idx_fk_pet_person 时,为什么 KEY 名为fk_pet_person 我怎样才能让它如此命名?

您混淆了 FOREIGN KEY 和使其工作的 INDEX。 请注意 - 代码中显示的约束定义中没有表达式名称(看起来像索引定义但不是)。

当没有合适的索引让约束起作用时,则自动创建该索引,并将约束名称用作索引名称。 如果存在合适的索引,则不会发生自动创建。

如果您希望索引具有定义的名称,则必须在创建约束之前在单独的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`);

或者

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 文档指定了创建外键的语法:

[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

我的代码没有设置[index_name]的原因有两个,而是索引名称自动与约束名称相同。 从 MySQL 8.0 参考手册第13.1.20.5 节外键约束的这段中可以看出两者:

在 MySQL 8.0.16 之前,如果未定义 CONSTRAINT 符号子句,或者未在 CONSTRAINT 关键字之后包含符号,则 InnoDB 和 NDB 存储引擎都将使用 FOREIGN_KEY index_name(如果已定义)。 在 MySQL 8.0.16 及更高版本中,忽略 FOREIGN_KEY index_name。

第一个原因是我在 MySQL 8.0.22 中运行代码。

第二个原因是我应该省略约束名称。

@akina 的答案中的解决方法确实使我能够为与约束名称不同的外键(索引)指定一个名称。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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