PostgreSQL Constraints: PRIMARY KEY, FOREIGN KEY, CHECK, UNIQUE & NOT NULL
Learn every major PostgreSQL constraint — PRIMARY KEY, FOREIGN KEY (with ON DELETE options), UNIQUE, CHECK, NOT NULL and DEFAULT — with real table examples.
PostgreSQL Constraints
Constraints are rules the database enforces automatically — they're what keep your data correct without relying on application code to catch every mistake.
NOT NULL
Rejects any insert/update that leaves the column empty.
name VARCHAR(100) NOT NULL
UNIQUE
Guarantees no two rows share the same value.
email VARCHAR(150) UNIQUE
A UNIQUE constraint spanning multiple columns means the combination must be unique, not each column individually:
UNIQUE (student_id, course_id)
PRIMARY KEY
Combines NOT NULL + UNIQUE, and marks the column as the table's main identifier. A table can have only one primary key (though it can span multiple columns).
id SERIAL PRIMARY KEY
FOREIGN KEY
Links a column to a row in another table, ensuring you can't reference something that doesn't exist.
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
customer_id INTEGER REFERENCES customers(id),
total NUMERIC(10, 2)
);
ON DELETE Behavior
Controls what happens to child rows when the referenced parent row is deleted:
customer_id INTEGER REFERENCES customers(id) ON DELETE CASCADE
-- deleting a customer also deletes their orders
customer_id INTEGER REFERENCES customers(id) ON DELETE SET NULL
-- deleting a customer just clears customer_id on their orders
customer_id INTEGER REFERENCES customers(id) ON DELETE RESTRICT
-- (the default) blocks deleting a customer that still has orders
CHECK
Enforces an arbitrary boolean condition on a column.
salary NUMERIC(10, 2) CHECK (salary > 0)
age INTEGER CHECK (age BETWEEN 18 AND 65)
DEFAULT
Not strictly a constraint, but works alongside them to fill in a value automatically.
is_active BOOLEAN DEFAULT true
Adding a Constraint to an Existing Table
ALTER TABLE employees ADD CONSTRAINT chk_salary CHECK (salary > 0);
Common Errors & Troubleshooting
ERROR: duplicate key value violates unique constraint— an insert/update tried to write a value that already exists in aUNIQUE/PRIMARY KEYcolumn; the error message names the specific constraint, which tells you exactly which column(s) conflicted.ERROR: insert or update on table "orders" violates foreign key constraint— you tried to reference acustomer_idthat doesn't exist incustomers; insert the parent row first, or double-check the ID you're referencing.ERROR: update or delete on table "customers" violates foreign key constrainton a DELETE — this means the defaultON DELETE RESTRICTbehavior is blocking you because dependent orders still exist; either delete/reassign those orders first, or addON DELETE CASCADE/SET NULLif that behavior is actually desired.
Key Takeaways
PRIMARY KEYis reallyNOT NULL+UNIQUEcombined, plus "this is the table's identity."FOREIGN KEY'sON DELETEclause decides how deleting a parent row cascades to its children.CHECKconstraints let the database itself reject invalid values, rather than trusting application code.