:: DEVELOPER ZONE
Starting from MySQL 3.23.44, InnoDB features
foreign key constraints.
The syntax of a foreign key constraint definition in
InnoDB looks like this:
[CONSTRAINTsymbol] FOREIGN KEY [id] (index_col_name, ...) REFERENCEStbl_name(index_col_name, ...) [ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION}] [ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION}]
Foreign keys definitions are subject to the following conditions:
Both tables must be InnoDB type and they must
not be temporary tables.
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. Starting with MySQL/InnoDB 4.1.2, such an index will be created on the referenced table automatically if it does not exist.
Index prefixes on foreign key columns are not supported. One
consequence of this is that BLOB and
TEXT columns cannot be included in a foreign
key, because indexes on those columns must always include a prefix
length.
If the CONSTRAINT
is given, it must be unique in the database. If it is not given,
symbolInnoDB creates the name automatically.
InnoDB rejects any INSERT or
UPDATE operation that attempts to create a
foreign key value in a child table without a matching candidate key
value in the parent table. The action InnoDB
takes for any UPDATE or DELETE
operation that attempts to update or delete a candidate key value in
the parent table that has some matching rows in the child table is
dependent on the referential action specified
using ON UPDATE and ON DETETE
subclauses of the FOREIGN KEY clause. When the
user attempts to delete or update a row from a parent table, and
there are one or more matching rows in the child table,
InnoDB supports five options regarding the action
to be taken:
CASCADE: Delete or update the row from the
parent table and automatically delete or update the matching rows
in the child table. ON DELETE CASCADE is
available starting from MySQL 3.23.50 and ON UPDATE
CASCADE is available starting from 4.0.8.
Between two tables,
you should not define several ON UPDATE CASCADE
clauses that act on the same column in the parent table or in the
child table.
SET NULL: Delete or update the row from the
parent table and set the foreign key column(s) in the child table
to NULL. This is only valid if the foreign key
columns do not have the NOT NULL qualifier
specified. ON DELETE SET NULL is available
starting from MySQL 3.23.50 and ON UPDATE SET
NULL is available starting from 4.0.8.
NO ACTION: In ANSI SQL-92
standard, NO ACTION means no
action in the sense that an attempt to delete or update
a primary key value will not be allowed to proceed if there is a
related foreign key value in the referenced table (Gruber,
Mastering SQL, 2000:181). Starting from 4.0.18
InnoDB rejects the delete or update operation
for the parent table.
RESTRICT: Rejects the delete or update operation
for the parent table. NO ACTION and
RESTRICT are the same as omitting the
ON DELETE or ON UPDATE
clause. (Some database systems have deferred checks, and
NO ACTION is a deferred check. In MySQL, foreign
key constraints are checked immediately, so NO
ACTION and RESTRICT are the same.)
SET DEFAULT: This action is recognized by the
parser, but InnoDB rejects table definitions
containing ON DELETE SET DEFAULT or ON
UPDATE SET DEFAULT clauses.
InnoDB supports the same options when the
candidate key in the parent table is updated. With
CASCADE, the foreign key column(s) in the child
table are set to new value(s) of the candidate key in the parent
table. In the same way, the updates cascade if updated column(s) in
the child table reference foreign keys in another table.
Note that InnoDB supports foreign key references
within a table and in these cases child table really means dependent
records within the table.
InnoDB needs indexes on foreign keys and
referenced keys so that foreign key checks can be fast and not
require a table scan. Starting with MySQL 4.1.2, the index on
the foreign key is created automatically. In older versions, the
indexes must be created explicitly or the creation of foreign key
constraints fails.
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.
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 previously 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. Since 4.0.21, cascading operations
may not be nested more than 15 levels.
A deviation from SQL standards:
Like MySQL in general, in an SQL statement that inserts, deletes, or
updates many rows, InnoDB checks UNIQUE and
FOREIGN KEY constraints row-by-row. According to
the SQL standard, the default behavior should be that constraints
are only checked after the WHOLE SQL statement has been processed.
Note: Currently, triggers are not activated by cascaded foreign key actions.
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 {RESTRICT | CASCADE | SET NULL | NO ACTION}]
[ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION}]
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 TABLEyourtablenameDROP FOREIGN KEYfk_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 confuses 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 FROMdb_nameLIKE '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 or ALTER TABLE operations.
InnoDB does not allow you to drop a table that is
referenced by a FOREIGN KEY constraint, unless
you do SET FOREIGN_KEY_CHECKS=0. 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.
© 1995-2005 MySQL AB. All rights reserved.

User Comments
Warning: query failed: Unknown column 'user.firstname' in 'field list' in /data0/sites/live/web-main/lib/mysql-cxn.php on line 69
Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /data0/sites/live/web-main/lib/docbook.php on line 245
Add your own comment.