| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
FOREIGN KEY Constraints Starting from MySQL 3.23.44, InnoDB features foreign key constraints.
The syntax of a foreign key constraint definition in InnoDB looks like
this:
[CONSTRAINT symbol] FOREIGN KEY [id] (index_col_name, ...)
REFERENCES tbl_name (index_col_name, ...)
[ON DELETE {CASCADE | SET NULL | NO ACTION | RESTRICT}]
[ON UPDATE {CASCADE | SET NULL | NO ACTION | RESTRICT}]
|
Both tables must be InnoDB type. In the referencing table, there must
be an index where the foreign key columns are listed as the first
columns in the same order. In the referenced table, there must be an index
where the referenced columns are listed as the first columns in
the same order. Index prefixes on foreign key columns are not supported.
InnoDB does not automatically create indexes on foreign keys or
referenced keys: You must create them explicitly. The indexes are needed
so that foreign key checks can be fast and not require a table scan.
Corresponding columns in the foreign key and the referenced key must
have similar internal data types inside InnoDB so that they can be
compared without a type conversion.
The size and the signedness of integer types has to be the same.
The length of string types need not be the same.
If you specify a SET NULL action, make sure that you
have not declared the columns in the child table as
NOT NULL.
If MySQL reports an error number 1005 from a CREATE TABLE statement,
and the error message string refers to errno 150, this means that the table
creation failed because a foreign key constraint was not correctly formed.
Similarly, if an ALTER TABLE fails and it refers to errno 150,
that means a foreign key definition would be incorrectly formed for the
altered table. Starting from MySQL 4.0.13, you can use SHOW INNODB
STATUS to display a detailed explanation of the latest InnoDB
foreign key error in the server.
Starting from MySQL 3.23.50, InnoDB does not check foreign key
constraints on those foreign key or referenced key values
that contain a NULL column.
A deviation from SQL standards: If in the parent table
there are several rows that have the same referenced key value,
then InnoDB acts in foreign key checks as if the other parent
rows with the same key value do not exist. For example,
if you have defined a RESTRICT type constraint, and there
is a child row with several parent rows, InnoDB does not allow
the deletion of any of those parent rows.
Starting from MySQL 3.23.50, you can also associate the
ON DELETE CASCADE or ON DELETE SET NULL clause with
the foreign key constraint. Corresponding ON UPDATE options
are available starting from 4.0.8. If ON DELETE CASCADE is
specified, and a row in the parent table is deleted, InnoDB
automatically deletes also all those rows in the child table
whose foreign key values are equal to the referenced key value in
the parent row. If ON DELETE SET NULL is specified, the
child rows are automatically updated so that the columns in the
foreign key are set to the SQL NULL value.
InnoDB performs cascading operations through a depth-first algorithm,
based on records in the indexes corresponding to the foreign key
constraints.
A deviation from SQL standards: If
ON UPDATE CASCADE or ON UPDATE SET NULL recurses to
update the same table it has already updated during the cascade,
it acts like RESTRICT. This means that you cannot use
self-referential ON UPDATE CASCADE or
ON UPDATE SET NULL operations.
This is to prevent infinite loops resulting from cascaded updates.
A self-referential ON DELETE SET NULL, on the other hand,
is possible from 4.0.13.
A self-referential ON DELETE CASCADE has been possible since ON
DELETE was implemented.
A simple example that relates parent and child tables through a
single-column foreign key:
CREATE TABLE parent(id INT NOT NULL,
PRIMARY KEY (id)
) TYPE=INNODB;
CREATE TABLE child(id INT, parent_id INT,
INDEX par_ind (parent_id),
FOREIGN KEY (parent_id) REFERENCES parent(id)
ON DELETE CASCADE
) TYPE=INNODB;
|
A more complex example in which a product_order table has foreign keys
for two other tables. One foreign key references a two-column index in the
product table. The other references a single-column index in the
customer table:
CREATE TABLE product (category INT NOT NULL, id INT NOT NULL,
price DECIMAL,
PRIMARY KEY(category, id)) TYPE=INNODB;
CREATE TABLE customer (id INT NOT NULL,
PRIMARY KEY (id)) TYPE=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),
FOREIGN KEY (product_category, product_id)
REFERENCES product(category, id)
ON UPDATE CASCADE ON DELETE RESTRICT,
INDEX (customer_id),
FOREIGN KEY (customer_id)
REFERENCES customer(id)) TYPE=INNODB;
|
Starting from MySQL 3.23.50, InnoDB allows you to add a new
foreign key constraint to a table by using ALTER TABLE:
ALTER TABLE yourtablename
ADD [CONSTRAINT symbol] FOREIGN KEY [id] (index_col_name, ...)
REFERENCES tbl_name (index_col_name, ...)
[ON DELETE {CASCADE | SET NULL | NO ACTION | RESTRICT}]
[ON UPDATE {CASCADE | SET NULL | NO ACTION | RESTRICT}]
|
Remember to create the required indexes first.
You can also add a self-referential foreign key constraint to a
table using ALTER TABLE.
Starting from MySQL 4.0.13, InnoDB supports the use of ALTER
TABLE to drop foreign keys:
ALTER TABLE yourtablename
DROP FOREIGN KEY fk_symbol
|
If the FOREIGN KEY clause included a CONSTRAINT name when you
created the foreign key, you can refer to that name to drop the foreign key.
(A constraint name can be given as of MySQL 4.0.18.) Otherwise, the
fk_symbol value is internally generated by InnoDB when the
foreign key is created. To find out the symbol when you want to drop a foreign
key, use the SHOW CREATE TABLE statement.
An example:
mysql> SHOW CREATE TABLE ibtest11c\G
*************************** 1. row ***************************
Table: ibtest11c
Create Table: CREATE TABLE `ibtest11c` (
`A` int(11) NOT NULL auto_increment,
`D` int(11) NOT NULL default '0',
`B` varchar(200) NOT NULL default '',
`C` varchar(175) default NULL,
PRIMARY KEY (`A`,`D`,`B`),
KEY `B` (`B`,`C`),
KEY `C` (`C`),
CONSTRAINT `0_38775` FOREIGN KEY (`A`, `D`)
REFERENCES `ibtest11a` (`A`, `D`)
ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `0_38776` FOREIGN KEY (`B`, `C`)
REFERENCES `ibtest11a` (`B`, `C`)
ON DELETE CASCADE ON UPDATE CASCADE
) TYPE=InnoDB CHARSET=latin1
1 row in set (0.01 sec)
mysql> ALTER TABLE ibtest11c DROP FOREIGN KEY 0_38775;
|
Starting from MySQL 3.23.50, the InnoDB parser allows you to use
backticks around table and column names in a
FOREIGN KEY ... REFERENCES ... clause.
Starting from MySQL 4.0.5, the InnoDB parser also takes into account
the lower_case_table_names system variable setting.
Before MySQL 3.23.50, ALTER TABLE or CREATE INDEX
should not be used in connection with tables that have foreign
key constraints or that are referenced in foreign key constraints:
Any ALTER TABLE removes all foreign key
constraints defined for the table. You should not use
ALTER TABLE with the referenced table, either. Instead,
use DROP TABLE and CREATE TABLE to modify the
schema. When MySQL does an ALTER TABLE it may internally
use RENAME TABLE, and that will confuse the
foreign key constraints that refer to the table.
In MySQL, a CREATE INDEX statement is processed as an
ALTER TABLE, so the same considerations apply.
Starting from MySQL 3.23.50, InnoDB returns the foreign key
definitions of a table as part of the output of the SHOW CREATE TABLE
statement:
SHOW CREATE TABLE tbl_name; |
From this version, mysqldump also produces correct definitions
of tables to the dump file, and does not forget about the foreign keys.
You can display the foreign key constraints for a table like this:
SHOW TABLE STATUS FROM db_name LIKE 'tbl_name' |
The foreign key constraints are listed in the Comment column of
the output.
When performing foreign key checks, InnoDB sets shared row
level locks on child or parent records it has to look at.
InnoDB checks foreign key constraints immediately; the check
is not deferred to transaction commit.
To make it easier to reload dump files for tables that have foreign key
relationships, mysqldump automatically includes a statement in the
dump output to set FOREIGN_KEY_CHECKS to 0 as of MySQL 4.1.1. This
avoids problems with tables having to be reloaded in a particular order
when the dump is reloaded. For earlier versions, you can disable the
variable manually within mysql when loading the dump file like this:
mysql> SET FOREIGN_KEY_CHECKS = 0; mysql> SOURCE dump_file_name; mysql> SET FOREIGN_KEY_CHECKS = 1; |
This allows you to import the tables in any order if the dump file contains
tables that are not correctly ordered for foreign keys. It also speeds
up the import operation. FOREIGN_KEY_CHECKS is available starting
from MySQL 3.23.52 and 4.0.3.
Setting FOREIGN_KEY_CHECKS to 0 can also be useful for ignoring
foreign key constraints during LOAD DATA operations.
InnoDB allows you to drop any table, even though that
would break the foreign key constraints that reference
the table. When you drop a table, the constraints that
were defined in its create statement are also dropped.
If you re-create a table that was dropped, it must have a definition that conforms to the foreign key constraints referencing it. It must have the right column names and types, and it must have indexes on the referenced keys, as stated earlier. If these are not satisfied, MySQL returns error number 1005 and refers to errno 150 in the error message string.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated on July, 26 2004 using texi2html 1.70.