Database constraint

A rule the database itself enforces, so invalid values and broken relationships are rejected no matter which code writes them.

make the database reject bad datarules on a table columnstop impossible values getting saveddatabse constraintthe form validates it but bad rows still show upprice can never be negativethis field should never be emptykeep broken relationships out of the database

See it

Live demo coming soon

What it is

A database constraint is a rule the database checks whenever data is written. NOT NULL requires a value, CHECK can reject a negative price, UNIQUE stops duplicates, and primary and foreign keys protect identity and relationships. The important part is where the rule lives: every script, worker, migration, and API has to pass the same gate.

Reach for constraints when a fact must remain true no matter which code path writes the row. Use CHECK (quantity > 0) for a row-level invariant and a foreign key for 'this customer must exist'. Keep friendly form validation too, but let it explain the rule while the constraint enforces it.

Check which database you are on before trusting the rule. MySQL parsed CHECK constraints and silently ignored them until 8.0.16 in 2019, so plenty of older schemas contain a CHECK that never rejected anything. Write a row that should fail and confirm the database actually refuses it.

Gotcha: adding a constraint to an old table can fail because bad rows are already there. Audit and repair the existing data before making the rule final. Also do not force a cross-row business process into a CHECK constraint: checks are best for facts available in the row, while multi-row invariants usually need a unique constraint, transaction, or carefully designed trigger.

Ask AI for it

Turn these business invariants into PostgreSQL constraints. Use NOT NULL for required values, CHECK for row-level rules, UNIQUE for duplicate prevention, and FOREIGN KEY with an explicit ON DELETE action for relationships. Give every constraint a descriptive name, query for existing violations first, and produce a repair migration before the enforcement migration. For large tables, add eligible CHECK and FOREIGN KEY constraints with NOT VALID and validate them later with VALIDATE CONSTRAINT. Map SQLSTATE 23502, 23503, 23505, and 23514 to clear field-specific API responses instead of a generic 500, and add one failing test for each invariant.

You might have meant

unique constraintprimary keyforeign keyschema migrationnormalization