Adding and Dropping UNIQUE and CHECK
Objectives
By the end of this lesson, you should be able to:
- Add a
UNIQUEconstraint to an existing column - Add a
CHECKconstraint to an existing column - Remove either one with
DROP CONSTRAINT
💡 Why this matters:
UNIQUEandCHECK(Module 3) don’t have to be decided atCREATE TABLEtime either. A rule discovered later, “emails must be unique,” “salary must be positive,” can be added to a table that’s already in use.
⚠️ A note on verification: every statement and result in this lesson was run against a real, live PostgreSQL 18 database, using the
employeestable from Module 3.
Adding UNIQUE
ALTER TABLE employees ADD CONSTRAINT employees_email_key UNIQUE (email);
This is a slightly different shape than the constraints seen so far, ADD CONSTRAINT name UNIQUE (column) names the constraint explicitly (constraint naming gets its own lesson next), rather than being declared inline inside CREATE TABLE. Once added, it behaves exactly like a UNIQUE declared from the start, a duplicate email is rejected the same way covered in Module 3.
Adding CHECK
ALTER TABLE employees ADD CONSTRAINT employees_salary_check CHECK (salary > 0);
INSERT INTO employees (first_name, last_name, email, salary, department)
VALUES ('Jordan', 'Blake', 'jordan.blake@example.com', -100, 'Sales');
ERROR: new row for relation "employees" violates check constraint "employees_salary_check"
Exactly like a CHECK declared inline (Module 3), this enforces the condition on every future INSERT and UPDATE. Adding a CHECK to a table that already has data also validates every existing row against it, adding a constraint that existing data already violates fails immediately, the same way SET NOT NULL does in the last lesson.
Dropping Either One
Both are removed the same way, by name:
ALTER TABLE employees DROP CONSTRAINT employees_email_key;
ALTER TABLE employees DROP CONSTRAINT employees_salary_check;
This is exactly why naming a constraint clearly matters, DROP CONSTRAINT needs to know precisely which one to remove.
Try It
- Add a
UNIQUEconstraint namedemployees_email_keyto theemailcolumn, then try inserting a duplicate email and confirm it’s rejected. - Add a
CHECKconstraint namedemployees_salary_checkrequiringsalary > 0, then try inserting a negative salary and confirm it’s rejected. - Drop both constraints by name, and confirm the same inserts that failed before now succeed.
- Explain, in your own words, why adding a
CHECKconstraint to a table that already has data might fail immediately, before any new row is even inserted.
Recap
ALTER TABLE ... ADD CONSTRAINT name UNIQUE (column)andADD CONSTRAINT name CHECK (condition)add these constraints to an existing table.- Adding either one validates existing data first, a table with data that already violates the new rule can’t have it added until the data is fixed.
ALTER TABLE ... DROP CONSTRAINT nameremoves a constraint by its name.
Next lesson: adding and dropping PRIMARY KEY and FOREIGN KEY, the constraints that define a table’s identity and its relationships.