Skip to content

Beginner: asking questions · Databases and the relational model · topic 3 of 62 · 35 min

Keys and relationships

Explanation

A primary key identifies exactly one row; a foreign key is a column that points to a primary key in another table. Tables relate one-to-one, one-to-many or many-to-many, and a many-to-many link needs a third, junction table such as order_items. In SQLite you must run PRAGMA foreign_keys = ON before foreign keys are enforced.

Why keys?

Two customers can share a name. Two Ravi Kumars in Delhi is not unusual. To point at exactly one row you need a value that never repeats. That value is a key, and keys are what let tables link to each other. This linking is the "relational" in relational database, an idea introduced by E. F. Codd at IBM in 1970.

Primary key

A primary key is a column (or a group of columns) whose value is unique for every row and never empty. A table has at most one primary key. In SHOP, customers.id, products.id and orders.id are primary keys. Order 104 means one order and nothing else.

Natural and surrogate keys

A natural key is a value from the real world that is already unique: a vehicle registration number, a bank IFSC code, a train number. A surrogate key is a number the database makes up only to be the key, like id 1, 2, 3.

  • Natural keys mean something, but they can change (people change email addresses and phone numbers), and some are private. An Aadhaar number should never be a key that is copied into many tables.
  • Surrogate keys never change and are small and fast. Most apps use them, and keep natural values in normal columns with a UNIQUE rule.

Composite keys

Sometimes one column is not enough. In order_items, an order can have many products and a product can appear in many orders, but the pair (order_id, product_id) appears only once. So the primary key is both columns together. A key made of more than one column is a composite key.

sql
SELECT order_id, product_id, qty, price FROM order_items WHERE order_id = 101;
-- 101 | 1 | 2 | 650
-- 101 | 2 | 3 | 160
Order 101 has two lines: product 1 (rice) and product 2 (dal). Inserting (101, 1) again fails with "UNIQUE constraint failed: order_items.order_id, order_items.product_id".

Foreign keys

A foreign key is a column whose values must match a primary key in another table. orders.customer_id is a foreign key that points to customers.id. Instead of copying Asha's name and city into every order, the order stores her id, 1. Her details live in one place, so changing her city is one update, not fifty.

sql
SELECT id, order_date, status FROM orders WHERE customer_id = 1;
-- 101 | 2025-01-05 | Delivered
-- 103 | 2025-02-14 | Delivered
-- 108 | 2025-04-02 | Placed
All orders of customer 1 (Asha Verma). WHERE keeps only the rows that match; module 2 covers it fully.

Three kinds of relationship

KindMeaningExampleHow it is built
One-to-oneEach row on one side matches at most one row on the otherA user and their profile settingsA foreign key that is also UNIQUE
One-to-manyOne row on one side, many on the otherOne customer has many ordersA foreign key on the "many" side (orders.customer_id)
Many-to-manyMany on both sidesOrders and productsA junction table (order_items) with two foreign keys

A junction table (also called a link or bridge table) sits between two tables and holds one row per pairing. order_items says "order 101 contains product 1" and can also store details of that pairing, like qty and the price paid.

An ER diagram in words

An ER (entity-relationship) diagram is a drawing of tables as boxes and relationships as lines. You can also write it in words:

output
customers (id PK) 1 ──< many  orders (id PK, customer_id FK)
orders    (id PK) 1 ──< many  order_items (order_id FK, product_id FK; PK = both)
products  (id PK) 1 ──< many  order_items
employees (id PK) 1 ──< many  employees (manager_id FK)   -- a table can point to itself
PK = primary key, FK = foreign key. Orders and products are many-to-many through order_items.

Referential integrity, and the SQLite switch

Referential integrity means every foreign key value points to a row that really exists. An order for customer 99, when there is no customer 99, is an orphan row. The database can block orphans for you, but SQLite does this only after you switch it on, once per connection.

sql
PRAGMA foreign_keys = ON;
INSERT INTO orders VALUES (109, 99, '2025-04-10', 'Placed');
-- Error: FOREIGN KEY constraint failed
Without the PRAGMA, SQLite would quietly save the orphan order. PostgreSQL and MySQL (InnoDB) enforce foreign keys by default.

Common mistakes

  • Forgetting PRAGMA foreign_keys = ON in SQLite, then finding orphan rows months later. Turn it on whenever your app opens a connection.
  • Storing many ids in one column, like products = '1,5,7'. You cannot join or check such a list. Use a junction table with one row per pair.
  • Using a name as the key. Names repeat and change. Use an id, and keep the name in its own column.
  • Giving the foreign key a different type from the key it points to (TEXT vs INTEGER). Keep the types the same.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Keys and relationships · 1/7

Keys and relationships

Two customers can have the same name. To point at exactly one row, we need keys.

Prefer a video by a teacher? Find free videos on “primary key foreign key one to many many to many junction table explained” on YouTube ↗

In real life: Courses and students at a college

A college portal has students and courses. One student takes many courses, and one course has many students, so it is many-to-many. The portal adds an enrolments table with student_id and course_id (the pair is the primary key) plus the semester and grade. A query on enrolments can list every course of one student, or every student of one course.

sql
CREATE TABLE enrolments (
  student_id INTEGER REFERENCES students(id),
  course_id  INTEGER REFERENCES courses(id),
  semester   TEXT,
  grade      TEXT,
  PRIMARY KEY (student_id, course_id)
);
A junction table: two foreign keys, and both together form the composite primary key.

Practice (0/4 done)

Task 1 · Code · SQL

customer_id in orders is a foreign key to customers.id. Show the orders of customer 2 (Ravi Kumar). Return the columns id, order_date and status. Use WHERE customer_id = 2.

Task 2 · Code · SQL

order_items is a junction table between orders and products. Which orders contain product 2 (Toor Dal)? Return order_id and qty from order_items for product_id 2.

Task 3 · Code · SQL

SQLite does not enforce foreign keys until you switch them on. Write two statements: first turn foreign key checks on, then ask SQLite whether they are on with PRAGMA foreign_keys; (it returns 1 for on, 0 for off).

Task 4 · Practice

Draw the SHOP database on paper (or in a notes app) as an ER diagram: one box per table (customers, products, orders, order_items) with its columns. Mark each primary key (PK) and foreign key (FK), draw the lines between tables, and label each line one-to-many or many-to-many.

Quick quiz

Question 1

1.What is a foreign key?

Question 2

2.One student takes many courses, and one course has many students. How do you model this?

Question 3

3.In SHOP, why is the primary key of order_items (order_id, product_id)?

Question 4

4.In SQLite, foreign keys are declared but you can still insert an order for customer 99, who does not exist. Why?

Question 5

5.Which is the best primary key for a customers table?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

What is a foreign key?

Answer: A column whose values must match a primary key in another (or the same) table

A foreign key links a row to a row in another table, like orders.customer_id to customers.id.

One student takes many courses, and one course has many students. How do you model this?

Answer: Add a junction table with student_id and course_id

Many-to-many needs a junction table with one row per pair.

In SHOP, why is the primary key of order_items (order_id, product_id)?

Answer: Because the pair is unique, while each column alone repeats

An order has many products and a product is in many orders, but each pair appears once.

In SQLite, foreign keys are declared but you can still insert an order for customer 99, who does not exist. Why?

Answer: Foreign key checks are off until PRAGMA foreign_keys = ON

SQLite enforces foreign keys only after the PRAGMA, once per connection.

Which is the best primary key for a customers table?

Answer: A surrogate id such as 1, 2, 3

Names repeat, cities repeat, and Aadhaar is private. A made-up id is safe and never changes.

What is a primary key?Related

Answer: A column whose value is unique for each row, used to identify it

A primary key (usually id) identifies exactly one row, so other tables can point to it.

From Designing the data model

A patient may see the same doctor many times. Why is PRIMARY KEY (patient_id, doctor_id) a bad key for appointments?Related

Answer: The pair repeats, so a second visit would be rejected

A pair key allows each pair only once. Use an id, and add the start time to tell visits apart.

From Modelling data: entities and relationships

In SQLite, what is the difference between INTEGER PRIMARY KEY and INTEGER PRIMARY KEY AUTOINCREMENT?Related

Answer: AUTOINCREMENT never reuses an id, even after deletes

Both fill in ids. Without AUTOINCREMENT, the id of a deleted last row can be used again.

From CREATE TABLE and constraints

Why is a customer's city stored in a customers table instead of on every order row?Related

Answer: So it is stored once and a change happens in one place

Storing a fact once avoids copies that can disagree. Orders refer to the customer by id.

From Joins: combining tables

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 2 more topics in “Databases and the relational model” before its exam: CREATE TABLE and constraints, The SQL language and your tools.
  2. Module 1 exam: Databases and the relational model · 15 questions · 25 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, SELECT: filtering and sorting. 62 topics left in the course before the final exam.

← Previous: Tables, rows, columns and data types