What is the difference in the following two CREATE TABLE
statements? (The first one uses KEY
and the second one does not.)
CREATE TABLE `title` (
`title` VARCHAR(255) NOT NULL,
`order_number` VARCHAR(35) NOT NULL,
KEY `order_number` (`order_number`),
CONSTRAINT `order_number_fk` FOREIGN KEY (`order_number`)
REFERENCES `order` (`order_number`) ON DELETE CASCADE
)
CREATE TABLE `title` (
`title` VARCHAR(255) NOT NULL,
`order_number` VARCHAR(35) NOT NULL,
CONSTRAINT `order_number_fk` FOREIGN KEY (`order_number`)
REFERENCES `order` (`order_number`) ON DELETE CASCADE
)
Both of them create valid tables. How are they different and which would I want to use?
Permissions. Creating a new table with a foreign key requires CREATE TABLE permission in the database, and ALTER permission on the schema in which the table is being created. Creating a foreign key in an existing table requires ALTER permission on the table.
A primary key is used to ensure data in the specific column is unique. A foreign key is a column or group of columns in a relational database table that provides a link between data in two tables. It uniquely identifies a record in the relational database table.
A foreign key joins a table to another table by referencing its primary key. A foreign key constraint specifies that the key can only contain values that are in the referenced primary key, and thus ensures the referential integrity of data that is joined on the two keys.
They are (almost*) the same.
When you create a foreign key constraint, an index is created on the relevant column(s) of the referencing table automatically if no suitable index already exists.
From the manual page on FOREIGN KEY Constraints:
InnoDB requires indexes on foreign keys and referenced keys so that foreign key checks can be fast and not require a table scan. 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.
Emphasis mine.
(*) I say almost the same because there a few subtle differences.
The name of the index
In the first version you have given the index an explicit name, but in the second version the name of the index is the same as the name of the constraint (if it is specified).
Compare the output of SHOW INDEX
in both cases:
Version 1:
Table Non_unique Key_name Seq_in_index Column_name ... title 1 order_number 1 order_number ...
Version 2:
Table Non_unique Key_name Seq_in_index Column_name ... title 1 order_number_fk 1 order_number ...
As you can see, the only difference here is the name of the index.
Silent dropping
Another subtle difference is that in the second case, as the documentation mentions, the automatically created index could be silently dropped when new indexes are added:
This index might be silently dropped later, if you create another index that can be used to enforce the foreign key constraint.
This means is that if you later create a multicolumn index on, for example, (order_number, title)
:
CREATE INDEX ix_order_number_title ON title (order_number, title);
Then run SHOW INDEX
again:
Version 1:
Table Non_unique Key_name Seq_in_index Column_name ... title 1 order_number 1 order_number ... title 1 ix_order_number_title 1 order_number ... title 1 ix_order_number_title 2 title ...
Version 2:
Table Non_unique Key_name Seq_in_index Column_name ... title 1 ix_order_number_title 1 order_number ... title 1 ix_order_number_title 2 title ...
Now you can see that the first version has two indexes but the second version has only one. With the second version, the index that was automatically created by the foreign key constraint was automatically dropped again when the multi-column index was added. Normally this isn't a serious issue because the new index makes the original index mostly redundant.
Which would I want to use?
Normally you don't need to worry about explicitly creating the index on the referencing table of a foreign key constraint.
But you might want to create an index explicitly if:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With