Using Primary Keys, Indices, and Composite Keys in MySQL
Introduction
In MySQL, a primary key is a field that uniquely identifies each record in a table. For instance, student_id
, employee_id
, client_id
, country_id
, and more. When you join two or more columns to make the primary identifier, it is referred to as a composite key. On the other hand, an index is a data structure that increases the performance of the database when searching records. Indices adopt rapid intelligent lookup and processing algorithms to efficiently scan records. When you define a column with the primary key attribute, MySQL automatically creates an index for speed purposes.
In a mission-critical application, your database might contain many related tables. For the database to operate effectively, the only way to clearly define the relationships between the tables is by using primary keys, indices, and composite keys. MySQL only allows one primary key per table but you can have as many indices as you want. Also, a primary key field can not accept duplicates or null values.
In this guide, you'll learn how to create primary keys, indices, and composite keys on your MySQL server.
Prerequisites
To follow along with this guide, you need a MySQL database server and user account.
1. Create a Sample Database
In this step, you'll set up a database.
Log in to your MySQL server and run the command below to create a
sample_db
database.mysql> CREATE DATABASE sample_db;
Output.
Query OK, 1 row affected (0.01 sec)
Switch to the new
sample_db
database.mysql> USE sample_db;
Output.
Database changed
With the sample database created, you can now start creating the different MySQL keys in the following steps.
2. Create Single-column-based Keys
Your database should have the correct keys from the ground up to avoid issues as your data grows. Therefore, you should plan ahead and identify the primary key column and any other columns that you want to index. In this step, you'll create a single-column-based primary key and index on a table.
Create an
employees
table. This table will contain four columns. Define theemployee_id
as the unique column using thePRIMARY KEY
statement. Then, use theAUTO_INCREMENT
keyword to allow MySQL to generate the nextemployee_id
in the series every time youINSERT
a new record. Next, index thephone
column using the statementINDEX(phone)
.mysql> CREATE TABLE employees ( employee_id BIGINT PRIMARY KEY AUTO_INCREMENT, first_name VARCHAR(50), last_name VARCHAR(50), phone VARCHAR(15), INDEX(phone) ) ENGINE = InnoDB;
Output.
Query OK, 0 rows affected (0.02 sec)
To ensure your table has the right indices, run the following command.
mysql> SELECT DISTINCT TABLE_NAME, INDEX_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = 'sample_db';
You should get the following output.
+------------+------------+-------------+ | TABLE_NAME | INDEX_NAME | COLUMN_NAME | +------------+------------+-------------+ | employees | PRIMARY | employee_id | | employees | phone | phone | +------------+------------+-------------+ 2 rows in set (0.00 sec)
Next,
INSERT
a record into theemployees
table to test if everything is working as expected.mysql> INSERT INTO employees(first_name, last_name, phone) VALUES ('JOHN', 'DOE', '11111');
Output.
Query OK, 1 row affected (0.01 sec)
Query the
employees
table to make sure the data is in place.mysql> SELECT employee_id, first_name, last_name FROM employees;
Output.
+-------------+------------+-----------+ | employee_id | first_name | last_name | +-------------+------------+-----------+ | 1 | JOHN | DOE | +-------------+------------+-----------+ 1 row in set (0.00 sec)
Attempt to violate the
PRIMARY KEY
unique constraint by adding an employee with an existingemployee_id
of1
.mysql> INSERT INTO employees(employee_id, first_name, last_name, phone) VALUES (1, 'MARY', 'ROE', '22222');
You should get the following error since MySQL does not accept duplicate values on the
PRIMARY KEY
columns.ERROR 1062 (23000): Duplicate entry '1' for key 'employees.PRIMARY'
3. Create Multi-column/Composite Keys
In the previous step, your primary key and indices were based on a single column. MySQL also supports composite keys. These are unique keys that use a combination of two or more columns to uniquely identify each record. For instance, consider a case where you want to store vendors' names and the products they supply on a single table. In this scenario, every distinct vendor can only have a single record for each unique product they supply.
To understand the above use-case better, create the
products_to_vendors
table using the statement below. In the table, use the statementPRIMARY KEY(vendor_name, product_name)
to set up thevendor_name
andproduct_name
as a multi-columnPRIMARY KEY
.mysql> CREATE TABLE products_to_vendors ( vendor_name VARCHAR(50), product_name VARCHAR(50), PRIMARY KEY (vendor_name, product_name) ) ENGINE = InnoDB;
Output.
Query OK, 0 rows affected (0.01 sec)
Make sure you have got the right indices.
mysql> SELECT DISTINCT TABLE_NAME, INDEX_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = 'sample_db' AND TABLE_NAME = 'products_to_vendors';
Output.
+---------------------+------------+--------------+ | TABLE_NAME | INDEX_NAME | COLUMN_NAME | +---------------------+------------+--------------+ | products_to_vendors | PRIMARY | vendor_name | | products_to_vendors | PRIMARY | product_name | +---------------------+------------+--------------+ 2 rows in set (0.00 sec)
Next,
INSERT
the following sample records into theproducts_to_vendors
table.mysql> INSERT INTO products_to_vendors(vendor_name, product_name) VALUES ('ABC Suppliers', 'WIRELESS MOUSE'); INSERT INTO products_to_vendors(vendor_name, product_name) VALUES ('XYZ Limited', 'TOUCH SCREEN'); INSERT INTO products_to_vendors(vendor_name, product_name) VALUES ('SPEED SOLUTION', 'POWER CABLES');
Output.
Query OK, 1 row affected (0.01 sec)
List the records from the
products_to_vendors
table.mysql> SELECT vendor_name, product_name FROM products_to_vendors;
Output.
+----------------+----------------+ | vendor_name | product_name | +----------------+----------------+ | ABC Suppliers | WIRELESS MOUSE | | SPEED SOLUTION | POWER CABLES | | XYZ Limited | TOUCH SCREEN | +----------------+----------------+ 3 rows in set (0.00 sec)
Attempt inserting a record that violates the composite key columns.
mysql> INSERT INTO products_to_vendors(vendor_name, product_name) VALUES ('ABC Suppliers', 'WIRELESS MOUSE');
MySQL server should now throw the following error.
ERROR 1062 (23000): Duplicate entry 'ABC Suppliers-WIRELESS MOUSE' for key 'products_to_vendors.PRIMARY'
However, since the same product(
WIRELESS MOUSE
) can be supplied by a different vendor, the following statement should succeed.mysql> INSERT INTO products_to_vendors(vendor_name, product_name) VALUES ('EXAMPLE COMPANY', 'WIRELESS MOUSE');
Output.
Query OK, 1 row affected (0.00 sec)
4. Create Keys on Existing MySQL Tables
Sometimes, you might forget to define keys when creating tables or find yourself in a situation where you want to index a column during the development process to speed up queries on your rapidly growing database. Luckily, MySQL provides you with the functionalities of creating keys on existing tables using the ALTER TABLE
statement.
Create a
products
table without specifying any keys.mysql> CREATE TABLE products ( product_id BIGINT, product_name VARCHAR(100), category_name VARCHAR(100), price DOUBLE ) ENGINE = InnoDB;
Output.
Query OK, 0 rows affected (0.01 sec)
Ensure you've not accidentally defined any indices by running the following statement.
mysql> SELECT DISTINCT TABLE_NAME, INDEX_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = 'sample_db' AND TABLE_NAME = 'products';
Output.
Empty set (0.00 sec)
Now, to define the
product_id
as thePRIMARY KEY
in theproducts
table, run the following statement.mysql> ALTER TABLE products ADD PRIMARY KEY(product_id);
Output.
Query OK, 0 rows affected (0.02 sec) Records: 0 Duplicates: 0 Warnings: 0
Next, use the following command to index the
product_name
column.ALTER TABLE products ADD INDEX product_name_index (`product_name`);
Output.
Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0
Then, query the
INFORMATION_SCHEMA
database again to see if you've enforced the new keys.mysql> SELECT DISTINCT TABLE_NAME, INDEX_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = 'sample_db' AND TABLE_NAME = 'products';
The output below confirms your indices are in place.
+------------+--------------------+--------------+ | TABLE_NAME | INDEX_NAME | COLUMN_NAME | +------------+--------------------+--------------+ | products | PRIMARY | product_id | | products | product_name_index | product_name | +------------+--------------------+--------------+ 2 rows in set (0.00 sec)
5. Benefits of Using Primary Keys, Indices, and Composite Keys
In every application, adding indices into your database tables allows you to:
Easily locate and identify records in large tables. For instance, if you have 1,000 employees on a table and you just want to locate a single staff member information, you can use their
employee_id
to look them up.Prevent duplicate entries. In most business transactions, duplicate records may lead to losses due to conflicting data. Since a primary key column does not allow duplicate entries, it is a good bet when it comes to validating data.
Update and delete records. MySQL requires a unique key in a
WHERE
clause to look up, andUPDATE
orDELETE
a single record.Define unique constraints and link related tables together. For instance, if you want to enforce referential integrity in your database, it would be impossible without using foreign keys.
Conclusion
This guide has focused on creating primary keys, indices, and composite keys on your MySQL server. While this is not a conclusive list of using MySQL indices, it should give you a good foundation to work with databases keys as a beginner.