SQLCHECK Constraint

CHECK Constraint

A CHECK constraint attaches a custom boolean condition to a table or column. Every row, whether inserted or later updated, must satisfy that condition — if the expression evaluates to false, the database rejects the operation. Where PRIMARY KEY, FOREIGN KEY, UNIQUE, and NOT NULL each enforce one specific, built-in kind of rule, CHECK lets you encode any business rule you can express as a boolean expression.

Worked example

SQL
CREATE TABLE products (
  product_id INT PRIMARY KEY,
  name       VARCHAR(100) NOT NULL,
  price      DECIMAL(10, 2) NOT NULL CHECK (price > 0),
  discount   DECIMAL(4, 2) DEFAULT 0 CHECK (discount BETWEEN 0 AND 1)
);

SQL
-- Fails: price must be greater than 0
INSERT INTO products (product_id, name, price)
VALUES (1, 'Widget', -5.00);
ERROR: new row for relation "products" violates check constraint "products_price_check"
DETAIL: Failing row contains (1, Widget, -5.00, 0.00).

Without this constraint, nothing stops a bug in an admin tool, a bad data import, or a careless manual UPDATE from setting a product's price to a negative number — a mistake that could silently corrupt every report and calculation built on top of the products table.

CHECK across multiple columns

A CHECK expression can reference more than one column, letting it enforce relationships between values in the same row:

SQL
CREATE TABLE bookings (
  booking_id  INT PRIMARY KEY,
  start_date  DATE NOT NULL,
  end_date    DATE NOT NULL,
  CHECK (end_date > start_date)
);

This guarantees that no booking can ever be stored with an end date on or before its start date, regardless of which application or script created the row.

Adding a named CHECK constraint

SQL
ALTER TABLE bookings
  ADD CONSTRAINT chk_booking_dates CHECK (end_date > start_date);

Naming a constraint explicitly (with CONSTRAINT chk_booking_dates) makes the resulting error messages clearer and makes the constraint easier to drop or modify later, compared to relying on an auto-generated name.

Note
Older versions of MySQL (before 8.0.16) parsed CHECK constraints but silently ignored them — they had no effect at all, and invalid data could still be inserted without any error. This was fixed in MySQL 8.0.16, where CHECK constraints are properly enforced. If working with an older MySQL version, do not rely on CHECK for correctness; validate in application code instead, or upgrade.
Tip
Use CHECK for rules specific to a single table's own columns (valid ranges, valid formats, logical relationships between two dates, etc.). For rules that depend on data in another table, a FOREIGN KEY constraint or a trigger is the appropriate tool instead — a CHECK expression cannot query other tables.