13.1.20.5 FOREIGN KEY Constraints外键约束

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

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.在子表上定义了外键约束。

The essential syntax for a defining a foreign key constraint in a CREATE TABLE or ALTER TABLE statement includes the following:CREATE TABLEALTER TABLE语句中定义外键约束的基本语法包括:

[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

Foreign key constraint usage is described under the following topics in this section:外键约束的使用在本节的以下主题下进行了说明:

Identifiers标识符

Foreign key constraint naming is governed by the following rules:外键约束命名受以下规则管辖:

  • The CONSTRAINT symbol value is used, if defined.将使用CONSTRAINT symbol(如果已定义)。

  • If the CONSTRAINT symbol clause is not defined, or a symbol is not included following the CONSTRAINT keyword, a constraint name name is generated automatically.如果未定义CONSTRAINT symbol子句,或者CONSTRAINT关键字后面未包含符号,则会自动生成约束名称。

    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 symbol子句,或者CONSTRAINT关键字后面未包含符号,InnoDBNDB存储引擎都将使用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 CONSTRAINT symbol value, if defined, must be unique in the database. CONSTRAINT symbol值(如果已定义)在数据库中必须是唯一的。A duplicate symbol results in an error similar to: ERROR 1005 (HY000): Can't create table 'test.fk1' (errno: 121).重复symbol会导致类似以下情况的错误:ERROR 1005 (HY000): Can't create table 'test.fk1' (errno: 121)

  • NDB Cluster stores foreign names using the same lettercase with which they are created. NDB Cluster使用创建外来名称时使用的同一个大写字母存储外来名称。Prior to version 8.0.20, when processing SELECT and other SQL statements, NDB compared the names of foreign keys in such statements with the names as stored in a case-sensitive fashion when lower_case_table_names was equal to 0. 在版本8.0.20之前,当处理SELECT和其他SQL语句时,NDB将此类语句中外键的名称与lower_case_table_names等于0时以区分大小写的方式存储的名称进行比较。In NDB 8.0.20 and later, this value no longer has any effect on how such comparisons are made, and they are always done without regard to lettercase. 在NDB 8.0.20及更高版本中,该值不再对如何进行此类比较产生任何影响,并且始终不考虑字母大小写。(Bug #30512043)

Table and column identifiers in a FOREIGN KEY ... REFERENCES clause can be quoted within backticks (`). FOREIGN KEY ... REFERENCES子句中的表和列标识符可以在反点符号(`)中引用。Alternatively, double quotation marks (") can be used if the ANSI_QUOTES SQL mode is enabled. 或者,如果启用了ANSI_QUOTES SQL模式,则可以使用双引号(")。The lower_case_table_names system variable setting is also taken into account.还考虑了lower_case_table_names系统变量设置。

Conditions and Restrictions条件和限制

Foreign key constraints are subject to the following conditions and restrictions:外键约束受以下条件和限制的约束:

  • Parent and child tables must use the same storage engine, and they cannot be defined as temporary tables.父表和子表必须使用相同的存储引擎,并且不能将它们定义为临时表。

  • Creating a foreign key constraint requires the REFERENCES privilege on the parent table.创建外键约束需要父表上的REFERENCES权限。

  • Corresponding columns in the foreign key and the referenced key must have similar data types. 外键和引用键中的相应列必须具有相似的数据类型。The size and sign of fixed precision types such as INTEGER and DECIMAL must be the same. INTEGERDECIMAL等固定精度类型的大小和符号必须相同The length of string types need not be the same. 字符串类型的长度不必相同。For nonbinary (character) string columns, the character set and collation must be the same.对于非二进制(字符)字符串列,字符集和排序规则必须相同。

  • MySQL supports foreign key references between one column and another within a table. MySQL支持表中一列和另一列之间的外键引用。(A column cannot have a foreign key reference to itself.) (列本身不能有外键引用。)In these cases, a child table record refers to a dependent record within the same table.在这些情况下,“子表记录”是指同一表中的从属记录。

  • MySQL requires indexes on foreign keys and referenced keys so that foreign key checks can be fast and not require a table scan. MySQL需要外键和引用键的索引,这样外键检查可以很快,而不需要扫描表。In the referencing table, there must be an index where the foreign key columns are listed as the first columns in the same order. 在引用表中,必须有一个索引,其中外键列按相同顺序列为第一列。Such an index is created on the referencing table automatically if it does not exist. 如果引用表不存在,则会自动在引用表上创建这样的索引。This index might be silently dropped later if you create another index that can be used to enforce the foreign key constraint. 如果您创建了另一个可用于强制外键约束的索引,则该索引可能会在以后以静默方式删除。index_name, if given, is used as described previously.index_name(如果给定)如前所述使用。

  • InnoDB permits a foreign key to reference any index column or group of columns. InnoDB允许外键引用任何索引列或列组。However, in the referenced table, there must be an index where the referenced columns are the first columns in the same order. 但是,在引用的表中,必须有一个索引,其中引用的列是相同顺序的第一列。Hidden columns that InnoDB adds to an index are also considered (see Section 15.6.2.1, “Clustered and Secondary Indexes”).InnoDB添加到索引中的隐藏列也会被考虑(请参阅第15.6.2.1节,“聚集索引和二级索引”)。

    NDB requires an explicit unique key (or primary key) on any column referenced as a foreign key. NDB要求在作为外键引用的任何列上有一个明确的唯一键(或主键)。InnoDB does not, which is an extension of standard SQL.InnoDB没有,它是标准SQL的扩展。

  • Index prefixes on foreign key columns are not supported. 外键列上的索引前缀不受支持。Consequently, BLOB and TEXT columns cannot be included in a foreign key because indexes on those columns must always include a prefix length.因此,BLOBTEXT列不能包含在外键中,因为这些列上的索引必须始终包含前缀长度。

  • InnoDB does not currently support foreign keys for tables with user-defined partitioning. InnoDB目前不支持具有用户定义分区的表的外键。This includes both parent and child tables.这包括父表和子表。

    This restriction does not apply for NDB tables that are partitioned by KEY or LINEAR KEY (the only user partitioning types supported by the NDB storage engine); these may have foreign key references or be the targets of such references.此限制不适用于按KEYLINEAR KEY分区的NDB表(NDB存储引擎支持的唯一用户分区类型);这些可能有外键引用或是此类引用的目标。

  • A table in a foreign key relationship cannot be altered to use another storage engine. 外键关系中的表不能更改为使用其他存储引擎。To change the storage engine, you must drop any foreign key constraints first.要更改存储引擎,必须先删除任何外键约束。

  • A foreign key constraint cannot reference a virtual generated column.外键约束无法引用虚拟生成的列。

For information about how the MySQL implementation of foreign key constraints differs from the SQL standard, see Section 1.7.2.3, “FOREIGN KEY Constraint Differences”.有关外键约束的MySQL实现如何不同于SQL标准的信息,请参阅第1.7.2.3节,“外键约束差异”

Referential Actions引用操作

When an UPDATE or DELETE 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. UPDATE操作或DELETE操作影响父表中具有子表中匹配行的键值时,结果取决于FOREIGN KEY子句的ON UPDATEON DELETE子类指定的引用操作。Referential actions include:引用操作包括:

  • CASCADE: Delete or update the row from the parent table and automatically delete or update the matching rows in the child table. :从父表中删除或更新行,并自动删除或更新子表中的匹配行。Both ON DELETE CASCADE and ON UPDATE CASCADE are supported. ON DELETE CASCADEON UPDATE CASCADE这两者都受支持。Between two tables, do not define several ON UPDATE CASCADE clauses that act on the same column in the parent table or in the child table.在两个表之间,不要定义多个作用于父表或子表中同一列的ON UPDATE CASCADE子句。

    If a FOREIGN KEY clause is defined on both tables in a foreign key relationship, making both tables a parent and child, an ON UPDATE CASCADE or ON DELETE CASCADE subclause defined for one FOREIGN KEY clause must be defined for the other in order for cascading operations to succeed. 如果在外键关系中的两个表上都定义了FOREIGN KEY子句,使两个表都成为父表和子表,则必须为另一个定义为一个FOREIGN KEY子句定义的ON UPDATE CASCADEON DELETE CASCADE子项,以便级联操作成功。If an ON UPDATE CASCADE or ON DELETE CASCADE subclause is only defined for one FOREIGN KEY clause, cascading operations fail with an error.如果只为一个FOREIGN KEY子句定义了ON UPDATE CASCADEON DELETE CASCADE子类,则级联操作将失败并出错。

    Note注意

    Cascaded foreign key actions do not activate triggers.级联外键操作不会激活触发器。

  • SET NULL: Delete or update the row from the parent table and set the foreign key column or columns in the child table to NULL. :删除或更新父表中的行,并将子表中的外键列设置为NULLBoth ON DELETE SET NULL and ON UPDATE SET NULL clauses are supported.ON DELETE SET NULLON UPDATE SET NULL这两个子句都受支持。

    If you specify a SET NULL action, make sure that you have not declared the columns in the child table as NOT NULL.如果指定SET NULL操作,请确保未将子表中的列声明为NOT NULL

  • RESTRICT: Rejects the delete or update operation for the parent table. :拒绝父表的删除或更新操作。Specifying RESTRICT (or NO ACTION) is the same as omitting the ON DELETE or ON UPDATE clause.指定RESTRICT(或NO ACTION)与省略ON DELETEON UPDATE子句相同。

  • NO ACTION: A keyword from standard SQL. :标准SQL中的关键字。In MySQL, equivalent to RESTRICT. 在MySQL中,相当于RESTRICTThe MySQL Server rejects the delete or update operation for the parent table if there is a related foreign key value in the referenced table. 如果引用的表中存在相关的外键值,MySQL服务器将拒绝父表的删除或更新操作。Some database systems have deferred checks, and NO ACTION is a deferred check. 有些数据库系统有延迟检查,则NO ACTION是延迟检查。In MySQL, foreign key constraints are checked immediately, so NO ACTION is the same as RESTRICT.在MySQL中,会立即检查外键约束,因此NO ACTIONRESTRICT相同。

  • SET DEFAULT: This action is recognized by the MySQL parser, but both InnoDB and NDB reject table definitions containing ON DELETE SET DEFAULT or ON UPDATE SET DEFAULT clauses.:MySQL解析器可以识别此操作,但InnoDBNDB都拒绝包含ON DELETE SET DEFAULT子句或ON UPDATE SET DEFAULT子句的表定义。

For storage engines that support foreign keys, MySQL rejects any INSERT or UPDATE operation that attempts to create a foreign key value in a child table if there is no matching candidate key value in the parent table.对于支持外键的存储引擎,如果父表中没有匹配的候选键值,MySQL将拒绝尝试在子表中创建外键值的任何INSERTUPDATE操作。

For an ON DELETE or ON UPDATE that is not specified, the default action is always NO ACTION.对于未指定的ON DELETEON UPDATE,默认操作始终为NO ACTION

As the default, an ON DELETE NO ACTION or ON UPDATE NO ACTION clause that is specified explicitly does not appear in SHOW CREATE TABLE output or in tables dumped with mysqldump. 默认情况下,显式指定的ON DELETE NO ACTIONON UPDATE NO ACTION子句不会出现在SHOW CREATE TABLE输出中或使用mysqldump转储的表中。RESTRICT, which is an equivalent non-default keyword, appears in SHOW CREATE TABLE output and in tables dumped with mysqldump.RESTRICT是一个等效的非默认关键字,出现在SHOW CREATE TABLE输出中和使用mysqldump转储的表中。

For NDB tables, ON UPDATE CASCADE is not supported where the reference is to the parent table's primary key.对于NDB表,如果引用是父表的主键,则不支持ON UPDATE CASCADE

As of NDB 8.0.16: For NDB tables, ON DELETE CASCADE is not supported where the child table contains one or more columns of any of the TEXT or BLOB types. 从NDB 8.0.16开始:对于NDB表,如果子表包含任何TEXTBLOB类型的一列或多列,则不支持ON DELETE CASCADE(Bug #89511, Bug #27484882)

InnoDB performs cascading operations using a depth-first search algorithm on the records of the index that corresponds to the foreign key constraint.InnoDB使用深度优先搜索算法对与外键约束对应的索引记录执行级联操作。

A foreign key constraint on a stored generated column cannot use CASCADE, SET NULL, or SET DEFAULT as ON UPDATE referential actions, nor can it use SET NULL or SET DEFAULT as ON DELETE referential actions.存储的生成列上的外键约束不能在更新引用操作上使用CASCADESET NULLSET DEFAULT,也不能在删除引用操作上使用SET NULLSET DEFAULT

A foreign key constraint on the base column of a stored generated column cannot use CASCADE, SET NULL, or SET DEFAULT as ON UPDATE or ON DELETE referential actions.存储的生成列的基列上的外键约束不能在ON UPDATEON DELETE引用操作时使用CASCADESET NULLSET DEFAULT

Foreign Key Constraint Examples外键约束示例

This simple example relates parent and child tables through a single-column foreign key:此简单示例通过单列外键关联parent表和child表:

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)
        ON DELETE CASCADE
) ENGINE=INNODB;

This is a more complex example in which a product_order table has foreign keys for two other tables. 这是一个更复杂的示例,其中一个product_order表具有另外两个表的外键。One foreign key references a two-column index in the product table. 一个外键引用product表中的两列索引。The other references a single-column index in the customer table:另一个引用customer表中的单列索引:

CREATE TABLE product (
    category INT NOT NULL, id INT NOT NULL,
    price DECIMAL,
    PRIMARY KEY(category, id)
)   ENGINE=INNODB;

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

CREATE TABLE product_order (
    no INT NOT NULL AUTO_INCREMENT,
    product_category INT NOT NULL,
    product_id INT NOT NULL,
    customer_id INT NOT NULL,

    PRIMARY KEY(no),
    INDEX (product_category, product_id),
    INDEX (customer_id),

    FOREIGN KEY (product_category, product_id)
      REFERENCES product(category, id)
      ON UPDATE CASCADE ON DELETE RESTRICT,

    FOREIGN KEY (customer_id)
      REFERENCES customer(id)
)   ENGINE=INNODB;
Adding Foreign Key Constraints添加外键约束

You can add a foreign key constraint to an existing table using the following ALTER TABLE syntax:可以使用以下ALTER TABLE语法将外键约束添加到现有表中:

ALTER TABLE tbl_name
    ADD [CONSTRAINT [symbol]] FOREIGN KEY
    [index_name] (col_name, ...)
    REFERENCES tbl_name (col_name,...)
    [ON DELETE reference_option]
    [ON UPDATE reference_option]

The foreign key can be self referential (referring to the same table). 外键可以是自引用的(引用同一个表)。When you add a foreign key constraint to a table using ALTER TABLE, remember to first create an index on the column(s) referenced by the foreign key.使用ALTER TABLE向表中添加外键约束时,请记住首先在外键引用的列上创建索引

Dropping Foreign Key Constraints删除外键约束

You can drop a foreign key constraint using the following ALTER TABLE syntax:可以使用以下ALTER TABLE语法删除外键约束:

ALTER TABLE tbl_name DROP FOREIGN KEY fk_symbol;

If the FOREIGN KEY clause defined a CONSTRAINT name when you created the constraint, you can refer to that name to drop the foreign key constraint. 如果在创建约束时FOREIGN KEY子句定义了CONSTRAINT名称,则可以引用该名称来删除外键约束。Otherwise, a constraint name was generated internally, and you must use that value. 否则,将在内部生成约束名称,您必须使用该值。To determine the foreign key constraint name, use SHOW CREATE TABLE:要确定外键约束名称,请使用SHOW CREATE TABLE

mysql> SHOW CREATE TABLE child\G
*************************** 1. row ***************************
       Table: child
Create Table: CREATE TABLE `child` (
  `id` int DEFAULT NULL,
  `parent_id` int DEFAULT NULL,
  KEY `par_ind` (`parent_id`),
  CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`)
  REFERENCES `parent` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

mysql> ALTER TABLE child DROP FOREIGN KEY `child_ibfk_1`;

Adding and dropping a foreign key in the same ALTER TABLE statement is supported for ALTER TABLE ... ALGORITHM=INPLACE. ALTER TABLE ... ALGORITHM=INPLACE支持在同一ALTER TABLE语句中添加和删除外键。It is not supported for ALTER TABLE ... ALGORITHM=COPY.ALTER TABLE ... ALGORITHM=COPY不支持它。

Foreign Key Checks外键检查

Foreign key checking is controlled by the foreign_key_checks variable, which is enabled by default. 外键检查由默认启用的foreign_key_checks变量控制。Typically, you leave this variable enabled during normal operation to enforce referential integrity. 通常,您会在正常操作期间启用此变量以强制引用完整性。The foreign_key_checks variable has the same effect on NDB tables as it does for InnoDB tables.foreign_key_checks变量对NDB表的作用与对InnoDB表的作用相同。

The foreign_key_checks variable is dynamic and supports both global and session scopes. foreign_key_checks变量是动态的,同时支持全局范围和会话范围。For information about using system variables, see Section 5.1.9, “Using System Variables”.有关使用系统变量的信息,请参阅第5.1.9节,“使用系统变量”

Disabling foreign key checking is useful when:在以下情况下禁用外键检查很有用:

  • Dropping a table that is referenced by a foreign key constraint. 删除外键约束引用的表。A referenced table can only be dropped after foreign_key_checks is disabled. 只有在禁用foreign_key_checks后,才能删除引用的表。When you drop a table, constraints defined on the table are also dropped.删除表时,也会删除表上定义的约束。

  • Reloading tables in different order than required by their foreign key relationships. 按与其外键关系不同的顺序重新加载表。For example, mysqldump produces correct definitions of tables in the dump file, including foreign key constraints for child tables. 例如,mysqldump在转储文件中生成正确的表定义,包括子表的外键约束。To make it easier to reload dump files for tables with foreign key relationships, mysqldump automatically includes a statement in the dump output that disables foreign_key_checks. 为了更容易地为具有外键关系的表重新加载转储文件,mysqldump在转储输出中自动包含一条语句,该语句禁用foreign_key_checksThis enables you to import the tables in any order in case the dump file contains tables that are not correctly ordered for foreign keys. 这使您能够在转储文件包含外键顺序不正确的表的情况下以任何顺序导入表。Disabling foreign_key_checks also speeds up the import operation by avoiding foreign key checks.禁用foreign_key_checks也可以通过避免外键检查来加快导入操作。

  • Executing LOAD DATA operations, to avoid foreign key checking.执行LOAD DATA操作,以避免外键检查。

  • Performing an ALTER TABLE operation on a table that has a foreign key relationship.对具有外键关系的表执行ALTER TABLE操作。

When foreign_key_checks is disabled, foreign key constraints are ignored, with the following exceptions:禁用foreign_key_checks时,将忽略外键约束,但以下情况除外:

  • Recreating a table that was previously dropped returns an error if the table definition does not conform to the foreign key constraints that reference the table. 如果表定义不符合引用该表的外键约束,则重新创建以前删除的表将返回错误。The table must have the correct column names and types. 表必须具有正确的列名和类型。It must also have indexes on the referenced keys. 它还必须在引用的键上具有索引。If these requirements are not satisfied, MySQL returns Error 1005 that refers to errno: 150 in the error message, which means that a foreign key constraint was not correctly formed.如果不满足这些要求,MySQL将返回错误1005,该错误消息中引用了errno:150,这意味着外键约束的格式不正确。

  • Altering a table returns an error (errno: 150) if a foreign key definition is incorrectly formed for the altered table.如果更改表的外键定义格式不正确,则更改表将返回错误(errno:150)。

  • Dropping an index required by a foreign key constraint. 删除外键约束所需的索引。The foreign key constraint must be removed before dropping the index.在删除索引之前,必须删除外键约束。

  • Creating a foreign key constraint where a column references a nonmatching column type.创建列引用不匹配列类型的外键约束。

Disabling foreign_key_checks has these additional implications:禁用foreign_key_checks会产生以下额外影响:

  • It is permitted to drop a database that contains tables with foreign keys that are referenced by tables outside the database.允许删除包含由数据库外部的表引用的外键表的数据库。

  • It is permitted to drop a table with foreign keys referenced by other tables.允许删除包含其他表引用的外键的表。

  • Enabling foreign_key_checks does not trigger a scan of table data, which means that rows added to a table while foreign_key_checks is disabled are not checked for consistency when foreign_key_checks is re-enabled.启用foreign_key_checks不会触发表数据扫描,这意味着在禁用foreign_key_checks时添加到表中的行在重新启用foreign_key_checks时不会检查一致性。

Locking锁定

MySQL extends metadata locks, as necessary, to tables that are related by a foreign key constraint. MySQL根据需要将元数据锁扩展到与外键约束相关的表。Extending metadata locks prevents conflicting DML and DDL operations from executing concurrently on related tables. 扩展元数据锁可防止冲突的DML和DDL操作在相关表上并发执行。This feature also enables updates to foreign key metadata when a parent table is modified. 此功能还允许在修改父表时更新外键元数据。In earlier MySQL releases, foreign key metadata, which is owned by the child table, could not be updated safely.在早期的MySQL版本中,子表拥有的外键元数据无法安全更新。

If a table is locked explicitly with LOCK TABLES, any tables related by a foreign key constraint are opened and locked implicitly. 如果表被LOCK TABLES显式锁定,则与外键约束相关的任何表都将被打开并隐式锁定。For foreign key checks, a shared read-only lock (LOCK TABLES READ) is taken on related tables. 对于外键检查,在相关表上使用共享只读锁(LOCK TABLES READ)。For cascading updates, a shared-nothing write lock (LOCK TABLES WRITE) is taken on related tables that are involved in the operation.对于级联更新,对操作中涉及的相关表执行无共享写锁(LOCK TABLES WRITE)。

Foreign Key Definitions and Metadata外键定义和元数据

To view a foreign key definition, use SHOW CREATE TABLE:要查看外键定义,请使用SHOW CREATE TABLE

mysql> SHOW CREATE TABLE child\G
*************************** 1. row ***************************
       Table: child
Create Table: CREATE TABLE `child` (
  `id` int DEFAULT NULL,
  `parent_id` int DEFAULT NULL,
  KEY `par_ind` (`parent_id`),
  CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`)
  REFERENCES `parent` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

You can obtain information about foreign keys from the INFORMATION_SCHEMA.KEY_COLUMN_USAGE table. 您可以从INFORMATION_SCHEMA.KEY_COLUMN_USAGE表中获取有关外键的信息。An example of a query against this table is shown here:针对该表的查询示例如下所示:

mysql> SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE REFERENCED_TABLE_SCHEMA IS NOT NULL;
+--------------+------------+-------------+-----------------+
| TABLE_SCHEMA | TABLE_NAME | COLUMN_NAME | CONSTRAINT_NAME |
+--------------+------------+-------------+-----------------+
| test         | child      | parent_id   | child_ibfk_1    |
+--------------+------------+-------------+-----------------+

You can obtain information specific to InnoDB foreign keys from the INNODB_FOREIGN and INNODB_FOREIGN_COLS tables. 您可以从INNODB_FOREIGNINNODB_FOREIGN_COLS表中获取特定于InnoDB外键的信息。Example queries are show here:示例查询如下所示:

mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_FOREIGN \G
*************************** 1. row ***************************
      ID: test/child_ibfk_1
FOR_NAME: test/child
REF_NAME: test/parent
  N_COLS: 1
    TYPE: 1

mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_FOREIGN_COLS \G
*************************** 1. row ***************************
          ID: test/child_ibfk_1
FOR_COL_NAME: parent_id
REF_COL_NAME: id
         POS: 0
Foreign Key Errors外键错误

In the event of a foreign key error involving InnoDB tables (usually Error 150 in the MySQL Server), information about the latest foreign key error can be obtained by checking SHOW ENGINE INNODB STATUS output.如果出现涉及InnoDB表的外键错误(MySQL服务器中通常为错误150),可以通过检查SHOW ENGINE INNODB STATUS输出来获取有关最新外键错误的信息。

mysql> SHOW ENGINE INNODB STATUS\G
...
------------------------
LATEST FOREIGN KEY ERROR
------------------------
2018-04-12 14:57:24 0x7f97a9c91700 Transaction:
TRANSACTION 7717, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
4 lock struct(s), heap size 1136, 3 row lock(s), undo log entries 3
MySQL thread id 8, OS thread handle 140289365317376, query id 14 localhost root update
INSERT INTO child VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5), (NULL, 6)
Foreign key constraint fails for table `test`.`child`:
,
  CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`) ON DELETE
  CASCADE ON UPDATE CASCADE
Trying to add in child table, in index par_ind tuple:
DATA TUPLE: 2 fields;
 0: len 4; hex 80000003; asc     ;;
 1: len 4; hex 80000003; asc     ;;

But in parent table `test`.`parent`, in index PRIMARY,
the closest match we can find is record:
PHYSICAL RECORD: n_fields 3; compact format; info bits 0
 0: len 4; hex 80000004; asc     ;;
 1: len 6; hex 000000001e19; asc       ;;
 2: len 7; hex 81000001110137; asc       7;;
...
Warning警告

If a user has table-level privileges for all parent tables, ER_NO_REFERENCED_ROW_2 and ER_ROW_IS_REFERENCED_2 error messages for foreign key operations expose information about parent tables. 如果用户对所有父表都具有表级权限,则外键操作的ER_NO_REFERENCED_ROW_2ER_ROW_IS_REFERENCED_2错误消息将公开有关父表的信息。If a user does not have table-level privileges for all parent tables, more generic error messages are displayed instead (ER_NO_REFERENCED_ROW and ER_ROW_IS_REFERENCED).如果用户不具有所有父表的表级权限,则会显示更一般的错误消息(ER_NO_REFERENCED_ROWER_ROW_IS_REFERENCED)。

An exception is that, for stored programs defined to execute with DEFINER privileges, the user against which privileges are assessed is the user in the program DEFINER clause, not the invoking user. 例外情况是,对于定义为使用DEFINER权限执行的存储程序,评估权限的用户是程序DEFINER子句中的用户,而不是调用用户。If that user has table-level parent table privileges, parent table information is still displayed. 如果该用户具有表级父表权限,则仍会显示父表信息。In this case, it is the responsibility of the stored program creator to hide the information by including appropriate condition handlers.在这种情况下,存储程序创建者有责任通过包含适当的条件处理程序来隐藏信息。