Primary Keys vs. Foreign Keys Explained for Beginners

If you’ve ever looked at a database diagram and wondered why every table has an id column, and why some tables have extra columns like customer_id sitting in them, this article is for you. Those columns are keys, and they’re what turn a pile of separate tables into a proper relational database.

There are two kinds you need to know as a beginner: primary keys and foreign keys. They sound technical, but the idea behind them is something you already use every day.

Diagram of a customers table primary key referenced by a foreign key in an orders table

An Everyday Way to Think About Keys

Think about your national ID card or your passport number. No two people share the same number, so it identifies you and only you. That’s a primary key.

Now think about a hospital appointment form. It doesn’t copy your whole life story onto the form. It just writes down your ID number, and anyone who needs your details can look you up. That ID number written on someone else’s form is a foreign key.

That’s really all there is to it. The rest is just learning how databases enforce those two ideas.

What Is a Primary Key?

A primary key is a column (or a group of columns) that uniquely identifies each row in a table. It has two strict rules:

  • It must be unique. No two rows can have the same value.
  • It can’t be empty. Every row must have a value, so NULL isn’t allowed.

Each table can have only one primary key. Here’s a simple customers table:

CREATE TABLE customers (
    customer_id INT PRIMARY KEY,
    name        VARCHAR(100) NOT NULL,
    email       VARCHAR(150)
);

If you try to insert two customers with customer_id = 1, the database refuses the second one. That’s the point. It protects you from duplicate records that would make your reports wrong.

Natural keys vs. surrogate keys

You’ll hear these two terms a lot:

TypeWhat it isExampleGood and bad
Natural keyA value that already exists in the real worldEmail address, national ID, ISBNMeaningful, but real-world values change (people change emails)
Surrogate keyA made-up number with no meaning outside the databasecustomer_id 1, 2, 3…Never changes and is fast, but means nothing on its own

Most developers, me included, use surrogate keys for almost everything. Let the database generate the number for you with AUTO_INCREMENT in MySQL, IDENTITY in SQL Server, or GENERATED ALWAYS AS IDENTITY in PostgreSQL:

-- SQL Server
CREATE TABLE customers (
    customer_id INT IDENTITY(1,1) PRIMARY KEY,
    name        NVARCHAR(100) NOT NULL
);

What Is a Foreign Key?

A foreign key is a column in one table that points to the primary key of another table. It’s how tables refer to each other.

Let’s add an orders table. Each order belongs to a customer, so instead of storing the customer’s name and email again in every order, we store their customer_id:

CREATE TABLE orders (
    order_id    INT PRIMARY KEY,
    customer_id INT NOT NULL,
    amount      DECIMAL(10,2),
    FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
);

The last line is the important one. It tells the database: “every value in orders.customer_id must already exist in customers.customer_id.”

order_idcustomer_idamount
101125.00
102380.50
103112.75

Notice that customer 1 appears twice. That’s fine. Unlike a primary key, a foreign key can repeat, because one customer can place many orders.

Primary Key vs. Foreign Key: Side by Side

Primary keyForeign key
JobIdentifies each row in its own tableLinks a row to a row in another table
Unique?Yes, alwaysNo, values can repeat
Can be NULL?NeverYes, unless you add NOT NULL
How many per table?Exactly oneAs many as you need
Examplecustomers.customer_idorders.customer_id

Why Bother? What Keys Protect You From

You could build tables without any keys and the database would happily store your data. The trouble shows up later. Keys give you something called referential integrity, which is a fancy way of saying “the links between tables always make sense”. In practice that means:

  • You can’t create an order for customer 99 if customer 99 doesn’t exist.
  • You can’t delete a customer who still has orders, unless you decide what should happen to those orders.
  • You never end up with “orphan” rows that point to nothing.

I’ve worked on older systems where the foreign keys were never created “to keep things simple”. Years later, the tables were full of orders pointing at deleted customers, and every report needed extra filters to hide the mess. Adding keys from day one is much cheaper than cleaning up afterwards.

What happens when you delete a parent row?

You get to choose. These options go on the foreign key:

OptionWhat it does
ON DELETE NO ACTION / RESTRICTBlocks the delete if child rows exist (the default in most databases)
ON DELETE CASCADEDeletes the child rows too
ON DELETE SET NULLKeeps the child rows but clears the foreign key value

Be careful with CASCADE. It’s convenient, but one delete can quietly remove hundreds of related rows.

How Keys Make JOINs Work

Keys and JOINs go hand in hand. When you want to see each order with the customer’s name, you join on the key columns:

SELECT o.order_id, c.name, o.amount
FROM orders o
JOIN customers c ON c.customer_id = o.customer_id;

The primary key on one side and the foreign key on the other are what make this join reliable. If you want a refresher on how joins work, see SQL JOINs Explained Simply.

Composite Keys (A Quick Mention)

Sometimes no single column is unique on its own, but a combination is. Picture a table that records which students are enrolled in which courses. A student appears many times and so does a course, but the pair (student, course) should only appear once:

CREATE TABLE enrollments (
    student_id INT,
    course_id  INT,
    PRIMARY KEY (student_id, course_id)
);

That’s a composite primary key. Both columns are usually also foreign keys pointing at students and courses.

Beginner Tips

  • Give every table a primary key. No exceptions.
  • Name keys clearly: customer_id in both tables is much easier to follow than id in one and cust in the other.
  • Make sure the foreign key column has the same data type as the primary key it points to.
  • Add an index on foreign key columns. Some databases do this for you and some (like SQL Server and PostgreSQL) don’t, and joins get slow without it.

Conclusion

A primary key answers “which row is this?” and a foreign key answers “which row does this belong to?”. Together they keep your data consistent and make it possible to connect tables with confidence.

Next time you design a table, start by deciding its primary key, then ask which other tables it needs to point to. If you’re still getting comfortable with querying, our guide to WHERE, ORDER BY and LIMIT is a good next read.

Scroll to Top