By the end of this lab, you will be able to: - Understand the concept and importance of foreign keys - Create tables with foreign key constraints - Understand referential integrity and its enforcement - Work with CASCADE operations (DELETE CASCADE, UPDATE CASCADE) - Handle foreign key constraint violations - Understand the relationship between parent and child tables
A foreign key is a column (or combination of columns) that creates a link between two tables. It ensures referential integrity by guaranteeing that values in the foreign key column must exist in the referenced table's primary key column.
If MySQL is not available, you can use SQLFiddle for online practice.
-- CREATE a clean DATABASE FOR FOREIGN KEY experiments
DROP DATABASE IF EXISTS foreign_key_lab;
CREATE DATABASE foreign_key_lab;
USE foreign_key_lab;
Important: Always create parent tables before child tables!
-- DROP TABLES IN correct ORDER (child first, THEN parent)
DROP TABLE IF EXISTS Enrolled; -- Child TABLE
DROP TABLE IF EXISTS Students; -- Parent TABLE
-- CREATE the parent TABLE first
CREATE TABLE Students (
sid CHAR(10) PRIMARY KEY, -- Student ID (PRIMARY KEY)
name CHAR(20), -- Student name
gpa FLOAT -- Grade Point Average
);
-- CREATE the child TABLE WITH FOREIGN KEY CONSTRAINT
CREATE TABLE Enrolled (
sid CHAR(10), -- Student ID (FOREIGN KEY)
cid CHAR(10), -- Course ID
grade CHAR(2), -- Letter grade
PRIMARY KEY (sid, cid), -- Composite PRIMARY KEY
FOREIGN KEY (sid) REFERENCES Students(sid) -- FOREIGN KEY CONSTRAINT
);
🤔 Why create Students before Enrolled?
The foreign key in Enrolled references the primary key in Students. MySQL needs the referenced table to exist first to validate the constraint.
-- INSERT students (parent TABLE data)
INSERT INTO Students VALUES('s1', 'Alice Johnson', 3.1);
INSERT INTO Students VALUES('s2', 'Bob Smith', 3.2);
INSERT INTO Students VALUES('s3', 'Carol Davis', 2.2);
INSERT INTO Students VALUES('s4', 'David Wilson', NULL); -- NULL GPA allowed
-- INSERT enrollments (child TABLE data)
INSERT INTO Enrolled VALUES('s1','cs101', 'A+');
INSERT INTO Enrolled VALUES('s1','cs102', 'A-');
INSERT INTO Enrolled VALUES('s1','cs103', 'B');
INSERT INTO Enrolled VALUES('s1','cs104', 'B');
INSERT INTO Enrolled VALUES('s2','cs101', 'A+');
INSERT INTO Enrolled VALUES('s2','cs103', 'A');
INSERT INTO Enrolled VALUES('s3','cs101', 'A-');
INSERT INTO Enrolled VALUES('s3','cs102', 'C');
INSERT INTO Enrolled VALUES('s3','cs105', 'B');
🔑 Key Point: Students must be inserted before their enrollments due to the foreign key constraint.
-- CHECK students TABLE
SELECT * FROM Students;
-- CHECK enrollments TABLE
SELECT * FROM Enrolled;
-- See the relationship IN action
SELECT s.name, e.cid, e.grade
FROM Students s
JOIN Enrolled e ON s.sid = e.sid
ORDER BY s.name, e.cid;
Try this command (it should fail):
INSERT INTO Enrolled VALUES('s5','cs105', 'B');
Expected Error:
Error Code: 1452. Cannot ADD OR UPDATE a child ROW: a FOREIGN KEY CONSTRAINT fails
Why it fails: Student 's5' doesn't exist in the Students table, violating referential integrity.
Try to delete a student who has enrollments:
DELETE FROM Students WHERE sid='s3';
Expected Error:
Error Code: 1451. Cannot DELETE OR UPDATE a parent ROW: a FOREIGN KEY CONSTRAINT fails
Why it fails: Student 's3' has enrollment records. Deleting the parent would leave orphaned child records.
Delete a student with no enrollments:
DELETE FROM Students WHERE sid='s4'; -- David Wilson has no enrollments
This works because 's4' has no dependent records in the Enrolled table.
To delete a student with enrollments, delete child records first:
-- Step 1: DELETE the student's enrollments
DELETE FROM Enrolled WHERE sid='s3';
-- Step 2: Now DELETE the student
DELETE FROM Students WHERE sid='s3';
Verify the deletion:
SELECT * FROM Students;
SELECT * FROM Enrolled;
Manual deletion is tedious. MySQL provides CASCADE options to automatically handle dependent records.
-- DROP existing TABLES
DROP TABLE IF EXISTS Enrolled;
DROP TABLE IF EXISTS Students;
-- Recreate WITH CASCADE DELETE
CREATE TABLE Students (
sid CHAR(10) PRIMARY KEY,
name CHAR(20),
gpa FLOAT
);
CREATE TABLE Enrolled (
sid CHAR(10),
cid CHAR(10),
grade CHAR(2),
PRIMARY KEY (sid, cid),
FOREIGN KEY (sid) REFERENCES Students(sid) ON DELETE CASCADE
);
-- INSERT fresh data
INSERT INTO Students VALUES('s1', 'Alice Johnson', 3.1);
INSERT INTO Students VALUES('s2', 'Bob Smith', 3.2);
INSERT INTO Students VALUES('s3', 'Carol Davis', 2.2);
INSERT INTO Enrolled VALUES('s1','cs101', 'A+');
INSERT INTO Enrolled VALUES('s1','cs102', 'A-');
INSERT INTO Enrolled VALUES('s2','cs101', 'A+');
INSERT INTO Enrolled VALUES('s3','cs101', 'A-');
INSERT INTO Enrolled VALUES('s3','cs102', 'C');
-- This will now WORK AND automatically DELETE related enrollments
DELETE FROM Students WHERE sid='s3';
Verify the cascade effect:
-- CHECK both TABLES - Carol Davis AND her enrollments should be gone
SELECT * FROM Students;
SELECT * FROM Enrolled;
🎉 Success! The CASCADE DELETE automatically removed Carol's enrollment records when we deleted her student record.
CREATE TABLE Enrolled (
sid CHAR(10),
cid CHAR(10),
grade CHAR(2),
PRIMARY KEY (sid, cid),
FOREIGN KEY (sid) REFERENCES Students(sid)
ON DELETE CASCADE
ON UPDATE CASCADE
);
-- User AND their posts (DELETE posts WHEN user IS deleted)
FOREIGN KEY (user_id) REFERENCES Users(id) ON DELETE CASCADE
-- ORDER AND customer (keep orders WHEN customer IS deleted, SET to NULL)
FOREIGN KEY (customer_id) REFERENCES Customers(id) ON DELETE SET NULL
-- Critical relationships (prevent accidental deletions)
FOREIGN KEY (department_id) REFERENCES Departments(id) ON DELETE RESTRICT
You've learned how to: ✅ Create foreign key constraints ✅ Understand referential integrity enforcement ✅ Handle constraint violations ✅ Use CASCADE operations for automatic maintenance ✅ Choose appropriate CASCADE options for different scenarios
Common Issues:
Useful Commands:
-- SHOW TABLE structure AND constraints
DESCRIBE table_name;
-- SHOW FOREIGN KEY constraints
SHOW CREATE TABLE table_name;