Foreign Keys
Complete MariaDB performance optimization guide. Complete reference for query tuning, indexing strategies, and configuration improvements for production use.
Overview
A foreign key is a constraint which can be used to enforce data integrity. It is composed of a column or a set of columns in a table, called the child table, which references to a column or a set of columns in a table called the parent table. With foreign keys, MariaDB performs checks to enforce that integrity rules are always enforced. For a more exhaustive explanation, see Relational databases: Foreign Keys.
Foreign keys can only be used with storage engines that support them. The default InnoDB supports foreign keys.
Partitioned tables cannot contain foreign keys, and cannot be referenced by a foreign key.
Syntax
CREATE TABLE b(for_key INT REFERENCES a(not_key));MariaDB applies the constraint if possible. See the Examples below.
Foreign keys are created with CREATE TABLE or ALTER TABLE. The foreign key definition has this syntax:
[CONSTRAINT [symbol]] FOREIGN KEY
[index_name] (index_col_name, ...)
REFERENCES tbl_name (index_col_name,...)
[ON DELETE reference_option]
[ON UPDATE reference_option]
reference_option:
RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULTThe symbol clause is used in error messages and must be unique per database, or, as of MariaDB 12.1, unique per table.
The symbol clause is optional. If it isn't specified, MariaDB automatically assigns one.
If MariaDB automatically creates an index for the foreign key (because it does not exist and is not explicitly created), its name is index_name.
Requirements and Limitations
Foreign keys have the following requirements:
Referenced columns in the parent table must be a an index or a prefix of an index.
Foreign key columns and referenced columns must be of the same type, or similar types. For integer types, the size and sign must also be the same.
For string types, the foreign key column and the referenced column must use the same character set and the same collation. Two columns that differ only in collation, such as
utf8mb4_general_ciandutf8mb4_uca1400_ai_ci, cannot be compared, so a foreign key between them is rejected. See Changing the Character Set or Collation of a Foreign Key Column.Both foreign key columns and referenced columns can be PERSISTENT columns. However, the
ON UPDATE CASCADE,ON UPDATE SET NULL,ON DELETE SET NULLclauses are not allowed in this case.The parent and the child table must use the same storage engine, and must not be
TEMPORARYor partitioned tables. However, they can be the same table.
Foreign keys in MariaDB have the following limitations:
Foreign key names must be unique per table.
Foreign key names must be unique per database.
Supported only by InnoDB.
Cannot be used with views.
The
SET DEFAULTaction is not supported.Foreign key actions do not activate triggers.
If
ON UPDATE CASCADErecurses to update the same table it has previously updated during the cascade, it acts likeRESTRICT.Indexed generated columns (both
VIRTUALandPERSISTENT) are not supported as InnoDB foreign key indexes.The columns in the child table must be a
BTREEindex (notHASH,RTREE, orFULLTEXT— see SHOW INDEX), or the leftmost part of aBTREEindex.
Constraints
If a foreign keys exists, each row in the child table must match a row in the parent table. Multiple child rows can match the same parent row. A child row matches a parent row if all its foreign key values are identical to the row values in the parent table. However, if at least one of the foreign key values is NULL, the row has no parent, but it is still allowed.
MariaDB performs certain checks to guarantee that data integrity is enforced:
Trying to insert non-matching rows (or update matching rows in a way that makes them non-matching rows) in the child table produces a 1452 error (SQLSTATE
23000).When a row in the parent table is deleted and at least one child row exists, MariaDB performs an action which depends on the
ON DELETEclause of the foreign key.When a value in the column referenced by a foreign key changes and at least one child row exists, MariaDB performs an action which depends on the
ON UPDATEclause of the foreign key.Trying to drop a table that is referenced by a foreign key produces a 1217 error (SQLSTATE '23000').
A TRUNCATE TABLE statement against a table containing one or more foreign keys is executed as a DELETE without a
WHEREclause, so that the foreign keys are enforced for each row.
The allowed actions for ON DELETE and ON UPDATE are:
RESTRICT: The change on the parent table is prevented. The statement terminates with a 1451 error (SQLSTATE '2300'). This is the default behavior for bothON DELETEandON UPDATE.NO ACTION: Synonym forRESTRICT.CASCADE: The change is allowed and propagates on the child table. For example, if a parent row is deleted, the child row is also deleted; if a parent row's ID changes, the child row's ID changes, too.SET NULL: The change is allowed, and the child row's foreign key columns are set toNULL.SET DEFAULT: This clause is not supported.
DELETE or UPDATE statements triggered by foreign keys do not activate triggers and are not counted in the Com_delete and Com_update status variables.
Foreign key constraints can be disabled by setting the foreign_key_checks server system variable to 0. This speeds up the insertion of large quantities of data.
Setting foreign_key_checks to 0 suspends the checks on data, but it does not permit schema changes that would leave the constraint itself invalid. Regardless of the setting, a column used in a foreign key cannot be dropped, renamed, or changed in a way that alters how its values compare, including a change of type, character set, or collation. See Changing the Character Set or Collation of a Foreign Key Column.
For detailed information about constraints, see this page.
Changing the Character Set or Collation of a Foreign Key Column
Because a foreign key requires both string columns to share a character set and collation, converting one table without the other breaks the constraint. MariaDB refuses the conversion rather than allowing it:
Converting the child table fails with error 1832,
Cannot change column '...': used in a foreign key constraint '...'.Converting the parent table fails with error 1833,
Cannot change column '...': used in a foreign key constraint '...' of table '...'.
Setting foreign_key_checks to 0 does not lift this restriction, and neither does requesting ALGORITHM=COPY or ALGORITHM=INPLACE. The conversion is rejected in every combination of the two. This is deliberate: allowing it would leave a foreign key whose columns can no longer be compared, producing a schema that cannot be restored from a dump.
Instead, drop the constraint, convert both tables, and re-create the constraint. Dropping it in the same ALTER TABLE statement as the column change is supported, so the child table needs only one statement:
The order matters. The parent table cannot be converted while a child foreign key still references it, and a child's constraint cannot be dropped from within the parent's ALTER TABLE. Across a whole schema, drop every affected constraint first, convert all the tables, then re-create the constraints.
Re-creating a constraint while foreign_key_checks is 0 does not validate the existing rows against it. To have them validated, restore foreign_key_checks to 1 before the ADD CONSTRAINT statement.
To list the constraints that need dropping and re-creating, query the KEY_COLUMN_USAGE table:
Converting a table to a different collation changes how its values compare and sort, which also changes what counts as a duplicate in a unique index. Where a conversion is only needed to make two tables match, converting the older tables forward to the newer collation is usually preferable to moving the newer ones back. See Setting Character Sets and Collations.
Metadata
The REFERENTIAL_CONSTRAINTS Information Schema table contains information about foreign keys:
The individual columns are listed in the KEY_COLUMN_USAGE table:
The InnoDB-specific Information Schema tables also contain information about the InnoDB foreign keys. The foreign key information is stored in the INNODB_SYS_FOREIGN table. Data about the individual columns are stored in INNODB_SYS_FOREIGN_COLS.
Another way of retrieving information about a table's foreign keys is the SHOW CREATE TABLE statement:
Examples
Creating and Using Foreign Keys
In this example, we create an author and a book table, both having a primary key called id. The book table also has a foreign key composed from a field called author_id, which refers to the author table primary key. The foreign key constraint name is optional, but we specify it because we want it to appear in error messages: fk_book_author.
When trying to insert a book with a non-existing author, we get an error:
The error basically says that author_id is mandatory because otherwise the foreign key constraint is violated. So, let's insert two authors and their books:
Those INSERT statements first add an author name to the name column of the author table, and the id column is automatically updated thanks to AUTO_INCREMENT. For the next INSERT statement (adding the book or books), we use the LAST_INSERT_ID() function, which uses that newly generated ID, filling it in for the book table.
Now, let's delete the second author from the author table. When we created the foreign key, we specified ON DELETE CASCADE. This propagates the deletion to the book table, making the deleted author's books disappear, too:
We also specified ON UPDATE RESTRICT. This prevents modifying an author's id (the column referenced by the foreign key) if a child row exists:
Referencing Keys in Tables
This example demonstrates which keys to reference for foreign keys, and what happens when the wrong key (not_key) is referenced (error 1005):
This page is licensed: CC BY-SA / Gnu FDL
Last updated
Was this helpful?

