Understanding Primary Keys: Ensuring Data Integrity in PostgreSQL
Learn how to define a Primary Key constraint to ensure data integrity in your PostgreSQL database. Master surrogate keys and serial IDs for your store schema.

Previously in this course, we discussed designing the products table and building the customers table. While we defined the columns for our store application, those tables lacked a fundamental mechanism to guarantee that each record remains distinct and identifiable. In this lesson, we introduce the Primary Key constraint to provide that guarantee.
What is a Primary Key?
A Primary Key is a column (or set of columns) that uniquely identifies every row in a table. Think of it as a fingerprint for your data. In a relational database, you must be able to point to a specific row without ambiguity. If you have two customers named "John Smith," a Primary Key ensures that the database knows exactly which "John Smith" you are updating or deleting.
A column designated as a Primary Key must satisfy two strict rules:
- Uniqueness: No two rows can have the same value in the Primary Key column.
- Non-nullability: A Primary Key cannot be
NULL. Every row must have a valid identifier.
The Power of Surrogate Keys
When designing databases, you might be tempted to use "natural" data as your identifier—like an email address or a SKU. However, natural keys are often unstable. If a customer changes their email address, or a product manufacturer changes their naming convention, your entire database relationship structure could break.
This is why we use Surrogate Keys. A surrogate key is an artificial identifier—usually an integer—that has no business meaning. It exists solely to identify the row. By using a surrogate key, you decouple your database’s internal identifiers from the real-world data, which makes your schema significantly more resilient to change. As discussed in Primary Keys and Identifiers: Designing for Data Integrity, surrogate keys are the gold standard for maintaining Data integrity in professional applications.
Implementing Serial IDs
PostgreSQL provides a convenient way to implement surrogate keys using the SERIAL pseudo-type. When you define a column as SERIAL, PostgreSQL automatically creates a sequence object that generates a unique, auto-incrementing integer every time you insert a new row.
Let’s apply this to our products table.
SQLCREATE TABLE products ( product_id SERIAL PRIMARY KEY, name TEXT NOT NULL, price NUMERIC(10, 2) NOT NULL, stock_quantity INTEGER DEFAULT 0 );
In the statement above:
product_id SERIAL: Automatically creates an integer column and hooks it to a sequence.PRIMARY KEY: Tells PostgreSQL to enforce uniqueness and disallowNULLvalues on this column.
Hands-on Exercise: Update your Schema
We need to make our customers table production-ready. Using the logic above, write a CREATE TABLE statement for the customers table that includes a surrogate Primary Key.
Task:
- Drop your existing
customerstable if it exists. - Create a new
customerstable with:customer_idas aSERIAL PRIMARY KEY.first_nameandlast_nameasTEXT.emailasTEXT.
SQL-- Example solution DROP TABLE IF EXISTS customers; CREATE TABLE customers ( customer_id SERIAL PRIMARY KEY, first_name TEXT NOT NULL, last_name TEXT NOT NULL, email TEXT );
Common Pitfalls
- Forgetting the PRIMARY KEY: It is common for beginners to define a table without a primary key. This makes it extremely difficult to perform targeted
UPDATEorDELETEoperations later. Always define one from the start. - Over-using Composite Keys: While you can use multiple columns as a primary key, it adds complexity to your queries and relationships. Stick to a single
SERIALorUUIDcolumn whenever possible. - Assuming Sequence Continuity: If you delete a row, the
SERIALID will not "fill the gap." If you insert IDs 1, 2, and 3, and delete 2, the next ID will be 4. Never rely on these IDs being perfectly sequential without gaps.
FAQ
Can a table have more than one Primary Key? A table can have only one Primary Key constraint. However, that constraint can be composed of multiple columns (a "composite key").
Should I use SERIAL or UUID?
SERIAL is perfect for beginners and small-to-medium applications. UUID (discussed later in this course) is better for distributed systems where you need to generate IDs on the client side before saving to the database.
What happens if I try to insert a duplicate ID?
PostgreSQL will throw a unique_violation error, preventing the transaction from completing, which is exactly the protection you need for your data.
Recap
Primary Keys are the foundation of relational Data integrity. By using SERIAL surrogate keys, you ensure that every record in your store database is uniquely addressable, regardless of changes to the underlying business data.
Up next: We will learn how to connect these tables together using Foreign Keys to establish relationships between your customers and their orders.
Work with me

Laravel SaaS MVP & Multi-Tenant App Development
Launch your SaaS MVP on Laravel — multi-tenant, subscription-ready, and built by the engineer behind a platform serving 10,000+ paying users.

AI Automation & Agentic Workflow Development
Automate the repetitive work eating your time — content pipelines, data workflows, and agentic AI tasks that run themselves.


