Skip to main content

Lesson 2 of 4 15 min read

Primary keys, foreign keys and relationships

Identify every row with a primary key and connect tables with foreign keys to model one-to-many and many-to-many relationships.

In this lesson you will

  • Explain why every table needs a primary key
  • Use foreign keys to link tables and protect referential integrity
  • Model one-to-many and many-to-many relationships

Primary keys

A primary key is a column (or set of columns) whose value uniquely identifies each row. It must be unique and never NULL. In our students table, id is the primary key: two students can share a name or a city, but never an id.

Most tables use a generated number or an identifier as the primary key rather than real-world data such as an email address, because real-world data can change. In PostgreSQL you can let the database generate it:

SQL
CREATE TABLE courses (
    id     INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    title  VARCHAR(150) NOT NULL,
    hours  INTEGER NOT NULL CHECK (hours > 0)
);

Why not one big table?

Imagine storing everything about enrolments in a single table:

student_namestudent_citycourse_titlecourse_hours
Asha MenonKochiSQL Essentials20
Asha MenonKochiPython Basics15
Ravi KumarChennaiSQL Essentials20

Asha's city and the hours of "SQL Essentials" are repeated. If the course length changes, every copy must be updated, and missing one leaves the data inconsistent. Relational design avoids this by storing each fact once and linking tables with keys. This process is called normalisation.

Foreign keys

A foreign key is a column that holds the primary key of a row in another table. It creates a relationship and lets the database protect it:

SQL
CREATE TABLE enrollments (
    student_id  INTEGER NOT NULL REFERENCES students (id),
    course_id   INTEGER NOT NULL REFERENCES courses (id),
    enrolled_on DATE    NOT NULL DEFAULT CURRENT_DATE,
    PRIMARY KEY (student_id, course_id)
);

With these foreign keys the database refuses to insert an enrolment for a student or course that doesn't exist, and refuses to delete a student who still has enrolments (unless you specify otherwise). This guarantee is called referential integrity.

The primary key (student_id, course_id) is a composite key: the pair must be unique, so a student cannot be enrolled in the same course twice.

Kinds of relationships

RelationshipMeaningExampleHow it's stored
One-to-manyOne row relates to many rows in another tableOne city has many studentsA foreign key on the "many" side
Many-to-manyMany rows relate to many rowsStudents take many courses; courses have many studentsA junction table with two foreign keys, like enrollments
One-to-oneExactly one related rowA user and their profile settingsA foreign key that is also unique
students and courses meet in the enrollments junction table

students (one) (contains enrollments (many): student_id points to students.id); courses (one) (contains enrollments (many): course_id points to courses.id)

You'll learn to combine tables with JOIN in a later course, but here is a preview of how keys make it possible:

SQL
SELECT s.name, c.title
FROM enrollments e
JOIN students s ON s.id = e.student_id
JOIN courses  c ON c.id = e.course_id;

The ON conditions match each enrolment's foreign keys to the primary keys they point to.

Hands-on exercise

A library has members, books and loans. Each loan records which member borrowed which book, the date borrowed and the date returned (which is empty until the book comes back). Sketch the three tables with their columns, mark each primary key and foreign key, and write the CREATE TABLE statement for loans. What kind of relationship is there between members and books?

Knowledge check

3 questions • 70% to pass • Practice only, no certificate

  1. 1.Why is a student's email usually a poor choice of primary key?
  2. 2.What happens if you insert an enrolment with a student_id that does not exist in students?
  3. 3.How is a many-to-many relationship between students and courses stored?
0 of 3 answered

Key concepts

  • A primary key uniquely identifies each row and can never be NULL.
  • Store each fact once and link tables with keys to avoid duplicated, inconsistent data.
  • A foreign key references another table's primary key and enforces referential integrity.
  • One-to-many relationships use a foreign key; many-to-many relationships use a junction table.