Constraints: Primary Key, Foreign Key, Unique, Check, Not Null

Constraints enforce data invariants regardless of which application writes the rows. PRIMARY KEY enforces uniqueness and non-nullness for the key; FOREIGN KEY enforces references; UNIQUE prevents duplicate values; CHECK enforces a boolean condition; NOT NULL requires a value. Defaults provide a value when an insert omits a column, but a default is not a substitute for a constraint.

Put critical rules in the database when possible. Application validation is still valuable for user-friendly error messages, but database constraints protect against bugs, scripts, concurrent requests, and other clients.

Use multiple constraints
CREATE TABLE memberships (
  user_id BIGINT NOT NULL,
  team_id BIGINT NOT NULL,
  role TEXT NOT NULL CHECK (role IN ('member', 'admin')),
  joined_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  PRIMARY KEY (user_id, team_id)
);
💡 The composite primary key prevents a user from being added to the same team twice. The CHECK constraint limits role values to the supported set.
Key Takeaways
  • Database constraints protect integrity across all clients.
  • A composite primary key can represent a many-to-many relationship.
  • Defaults do not replace NOT NULL or CHECK constraints.
Knowledge Check

Which constraint can restrict a role column to a known set of allowed values?