FOREIGN KEY创建的差异

时间:2012-06-24 19:41:39

标签: mysql

以下两个CREATE TABLE陈述有何不同? (第一个使用KEY而第二个不使用。)

CREATE TABLE `title` (
    `title` VARCHAR(255) NOT NULL,
    `order_number` VARCHAR(35) NOT NULL,
    KEY `order_number` (`order_number`),
    CONSTRAINT `order_number_fk` FOREIGN KEY (`order_number`)
        REFERENCES `order` (`order_number`) ON DELETE CASCADE
)

CREATE TABLE `title` (
    `title` VARCHAR(255) NOT NULL,
    `order_number` VARCHAR(35) NOT NULL,
    CONSTRAINT `order_number_fk` FOREIGN KEY (`order_number`)
        REFERENCES `order` (`order_number`) ON DELETE CASCADE
)

他们都创建有效的表。它们有什么不同,我想用哪个?

1 个答案:

答案 0 :(得分:7)

它们(几乎*)相同。

创建外键约束时,如果没有合适的索引,则会自动在引用表的相关列上创建索引。

来自FOREIGN KEY Constraints的手册页:

  

InnoDB需要外键和引用键的索引,以便外键检查速度快,不需要进行表扫描。在引用表中,必须有一个索引,其中外键列以相同的顺序列为第一列。 如果引用表不存在,则会自动在引用表上创建此索引。如果您创建另一个可用于强制执行外键约束的索引,则此索引可能会在以后静默删除。如果给定,则使用index_name,如前所述。

强调我的。


(*)我说几乎相同,因为有一些微妙的差异。

索引的名称

在第一个版本中,您为索引指定了显式名称,但在第二个版本中,索引的名称与约束的名称相同(如果已指定)。

在两种情况下比较SHOW INDEX的输出:

版本1:

Table  Non_unique  Key_name          Seq_in_index   Column_name   ...
title  1           order_number      1              order_number  ...

第2版:

Table  Non_unique  Key_name          Seq_in_index   Column_name   ...
title  1           order_number_fk   1              order_number  ...

如您所见,这里唯一的区别是索引的名称。

无声下降

另一个细微的区别是,在第二种情况下,正如文档所提到的,添加新索引时可以静默删除自动创建的索引:

  

如果您创建另一个可用于强制执行外键约束的索引,则可以稍后以静默方式删除此索引。

这意味着如果您以后创建多列索引,例如(order_number, title)

CREATE INDEX ix_order_number_title ON title (order_number, title);

然后再次运行SHOW INDEX

版本1:

Table  Non_unique  Key_name               Seq_in_index   Column_name   ...
title  1           order_number           1              order_number  ...
title  1           ix_order_number_title  1              order_number  ...
title  1           ix_order_number_title  2              title         ...

第2版:

Table  Non_unique  Key_name               Seq_in_index   Column_name   ...
title  1           ix_order_number_title  1              order_number  ...
title  1           ix_order_number_title  2              title         ...

现在您可以看到第一个版本有两个索引,但第二个版本只有一个。对于第二个版本,添加多列索引时,外键约束自动创建的索引会再次自动删除。通常这不是一个严重的问题,因为新索引使原始索引多数是多余的。

  

我想用哪个?

通常,您不必担心在外键约束的引用表上显式创建索引。

但您可能希望在以下情况下明确创建索引:

  • 您希望为其指定一个与约束名称不同的名称,或
  • 当您添加其他索引时,您不希望索引以静默方式消失。