8.4 中文镜像

MySQL 8.4 参考手册 · 中文镜像

正文为中文,英文原文默认隐藏。点击任意中文段落即可展开 / 收起对应英文原文。

打开官方英文原文 ↗

译文由机器翻译生成,仅供理解参考;有疑问请以官方英文原文为准。

中文点击中文段落可显示 / 隐藏英文原文本页译文覆盖 100%

5.6.6 使用外键5.6.6 Using Foreign Keys

MySQL 支持外键,它允许在表之间交叉引用相关数据,并且支持外键约束,这有助于保持相关数据的一致性。MySQL supports foreign keys, which permit cross-referencing related data across tables, and foreign key constraints, which help keep the related data consistent.

外键关系涉及一个父表,该表持有初始列值,以及一个子表,其列值引用父列值。外键约束在子表上定义。A foreign key relationship involves a parent table that holds the initial column values, and a child table with column values that reference the parent column values. A foreign key constraint is defined on the child table.

以下示例通过单列外键关联parent和child表,并展示了外键约束如何强制执行参照完整性。This following example relates parent and child tables through a single-column foreign key and shows how a foreign key constraint enforces referential integrity.

使用以下 SQL 语句创建父表和子表:Create the parent and child tables using the following SQL statements:

CREATE TABLE parent (
    id INT NOT NULL,
    PRIMARY KEY (id)
) ENGINE=INNODB;


CREATE TABLE child (
    id INT,
    parent_id INT,
    INDEX par_ind (parent_id),
    FOREIGN KEY (parent_id)
        REFERENCES parent(id)
) ENGINE=INNODB;

向父表插入一行,如下所示:Insert a row into the parent table, like this:

mysql> INSERT INTO parent (id) VALUES ROW(1);

验证数据是否已插入。您可以通过从 parent 中选择所有行来简单地完成此操作,如下所示:Verify that the data was inserted. You can do this simply by selecting all rows from parent, as shown here:

mysql> TABLE parent;
+----+
| id |
+----+
|  1 |
+----+

使用以下 SQL 语句向子表插入一行:Insert a row into the child table using the following SQL statement:

mysql> INSERT INTO child (id,parent_id) VALUES ROW(1,1);

插入操作成功,因为父表中存在 parent_id 1。The insert operation is successful because parent_id 1 is present in the parent table.

向子表插入一个在父表中不存在的 parent_id 值的行会被拒绝并报错,如下所示:Insertion of a row into the child table with a parent_id value that is not present in the parent table is rejected with an error, as you can see here:

mysql> INSERT INTO child (id,parent_id) VALUES ROW(2,2);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails 
(`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) 
REFERENCES `parent` (`id`))

操作失败,因为指定的 parent_id 值在父表中不存在。The operation fails because the specified parent_id value does not exist in the parent table.

尝试从父表中删除之前插入的行也会失败,如下所示:Trying to delete the previously inserted row from the parent table also fails, as shown here:

mysql> DELETE FROM parent WHERE id VALUES = 1;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails 
(`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) 
REFERENCES `parent` (`id`))

此操作失败,因为子表中的记录包含被引用的 id(parent_id)值。This operation fails because the record in the child table contains the referenced id (parent_id) value.

当操作影响父表中的关键值,而子表中存在匹配的行时,结果取决于 ON UPDATE 子句的 ON UPDATE 和 ON DELETE 子句指定的参照操作。在当前子表定义中省略 ON DELETE 和 FOREIGN KEY 子句,与指定 RESTRICT 选项相同,它会拒绝对父表中具有匹配行的关键值进行的操作。When an operation affects a key value in the parent table that has matching rows in the child table, the result depends on the referential action specified by ON UPDATE and ON DELETE subclauses of the FOREIGN KEY clause. Omitting ON DELETE and ON UPDATE clauses (as in the current child table definition) is the same as specifying the RESTRICT option, which rejects operations that affect a key value in the parent table that has matching rows in the parent table.

为了演示 ON DELETE 和 ON UPDATE 参照操作,请删除子表并重新创建它,以包含带有 CASCADE 选项的 ON UPDATE 和 ON DELETE 子子句。当在父表中删除或更新行时,CASCADE 选项会自动删除或更新子表中匹配的行。To demonstrate ON DELETE and ON UPDATE referential actions, drop the child table and recreate it to include ON UPDATE and ON DELETE subclauses with the CASCADE option. The CASCADE option automatically deletes or updates matching rows in the child table when deleting or updating rows in the parent table.

DROP TABLE child;

CREATE TABLE child (
    id INT,
    parent_id INT,
    INDEX par_ind (parent_id),
    FOREIGN KEY (parent_id)
        REFERENCES parent(id)
        ON UPDATE CASCADE
        ON DELETE CASCADE
) ENGINE=INNODB;

使用此处显示的语句向子表中插入一些行:Insert some rows into the child table using the statement shown here:

mysql> INSERT INTO child (id,parent_id) VALUES ROW(1,1), ROW(2,1), ROW(3,1);

像这样验证数据是否已插入:Verify that the data was inserted, like this:

mysql> TABLE child;
+------+-----------+
| id   | parent_id |
+------+-----------+
|    1 |         1 |
|    2 |         1 |
|    3 |         1 |
+------+-----------+

使用此处显示的 SQL 语句更新父表中的 ID,将其从 1 改为 2:Update the ID in the parent table, changing it from 1 to 2, using the SQL statement shown here:

mysql> UPDATE parent SET id = 2 WHERE id = 1;

通过从父表中选择所有行来验证更新是否成功,如下所示:Verify that the update was successful by selecting all rows from the parent table, as shown here:

mysql> TABLE parent;
+----+
| id |
+----+
|  2 |
+----+

验证 ON UPDATE CASCADE 参照操作更新了子表,如下所示:Verify that the ON UPDATE CASCADE referential action updated the child table, like this:

mysql> TABLE child;
+------+-----------+
| id   | parent_id |
+------+-----------+
|    1 |         2 |
|    2 |         2 |
|    3 |         2 |
+------+-----------+

要演示 ON DELETE CASCADE 参照操作,请删除父表中 parent_id = 2 的记录;这将删除父表中的所有相关记录。To demonstrate the ON DELETE CASCADE referential action, delete records from the parent table where parent_id = 2; this deletes all records in the parent table.

mysql> DELETE FROM parent WHERE id = 2;

由于子表中的所有记录都与 parent_id = 2 相关联,ON DELETE CASCADE 参照操作会删除子表中的所有记录,如下所示:Because all records in the child table are associated with parent_id = 2, the ON DELETE CASCADE referential action removes all records from the child table, as shown here:

mysql> TABLE child;
Empty set (0.00 sec)

有关外键约束的更多信息,请参见 第 15.1.20.5 节,“FOREIGN KEY 约束”。For more information about foreign key constraints, see Section 15.1.20.5, “FOREIGN KEY Constraints”.