One of the most asked for feature from the community,
support for CHECK constraints, is available in MySQL starting from version 8.0.16. This talk will provide introduction to this
new feature to our users. It will cover its syntax, semantics and
limitations. Also some typical use cases for this feature will be
studied.
2. Agenda
• Check Constraints on a High Level
• Creating Check Constraints
• Check Constraints Evaluation
• Check Constraint Expressions
• Altering/Dropping Check Constraints
• INFORMATION_SCHEMA Tables
3. Check Constraint on a High Level ...
• Is a type of table integrity constraint (similar to PRIMARY KEY, FOREIGN KEY,
UNIQUE and NOT NULL)
• Specifies requirement to be met by each row
– As a boolean expression
– Can refer a single or multiple columns
– Result can be TRUE/FALSE and UNKNOWN (if NULLs are involved)
– Constraint is satisfied if result is TRUE or UNKNOWN
4. A Bit of History
Wait, but aren’t Check Constraints supported by MySQL before 8.0?
• Before 8.0 syntax is accepted but ignored!
• Proper support starting from 8.0.16
– Improvements in 8.0.19
5. Basic example:
CREATE TABLE employees (
id INT PRIMARY KEY CHECK(id > 0),
name VARCHAR(255) NOT NULL,
hire_date DATE NOT NULL,
end_date DATE,
CHECK(end_date > hire_date)
);
Column constraint
can refer only to its column
For current employees
end_date is NULL,
expression is UNKNOWN,
thus constraint is satisfied
6. Typical Use Scenarios
• Limit value range
• Allow only certain
values/values that match
pattern
• Enforce relations
between columns of a
same row
CREATE TABLE employees (
id INT PRIMARY KEY CHECK(id > 0),
name VARCHAR(255) NOT NULL,
age INT CHECK (age > 18),
hire_date DATE NOT NULL,
end_date DATE,
country VARCHAR(10),
zip VARCHAR(10),
CHECK(country <> “RUS” OR LENGTH(zip) = 6),
CHECK(end_date > hire_date)
);
7. Creating Check Constraints: Syntax
CREATE TABLE supports the following SQL-standard syntax in column definition and
table definition:
[ CONSTRAINT [symbol] ] CHECK (condition) [ [ NOT ] ENFORCED ]
CREATE TABLE employees (
id INT PRIMARY KEY CONSTRAINT id_check CHECK(id > 0),
name VARCHAR(255) NOT NULL,
hire_date DATE NOT NULL,
end_date DATE,
CONSTRAINT end_date_check CHECK(end_date > hire_date)
);
8. Naming
[ CONSTRAINT [symbol] ] CHECK (condition) [ [ NOT ] ENFORCED ]
• CONSTRAINT [symbol] clause is optional
• Generated names format: <table_name>_chk_<ordinal_number>
• Separate namespace from UNIQUE and FOREIGN KEY constraints (non-
standard)
9. Naming Example
CREATE TABLE employees (
id INT PRIMARY KEY
CONSTRAINT id_check CHECK(id > 0),
name VARCHAR(255) NOT NULL,
hire_date DATE NOT NULL,
end_date DATE,
CHECK(end_date > hire_date)
);
SHOW CREATE TABLE employeesG
....
Create Table: CREATE TABLE `employees` (
`id` int(11) NOT NULL,
`name` varchar(255) NOT NULL,
`hire_date` date NOT NULL,
`end_date` date DEFAULT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `employees_chk_1` CHECK
((`end_date` > `hire_date`)),
CONSTRAINT `id_check` CHECK ((`id` > 0))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_0900_ai_ci
10. [NOT] ENFORCED clause
[ CONSTRAINT [symbol] ] CHECK (condition) [ [ NOT ] ENFORCED ]
• Optional clause which allows to control whether constraint is enforced or not
• ENFORCED is default
• Add NOT ENFORCED to create check constraint which won’t be enforced
• Can be changed later using ALTER TABLE
11. Adding check constraints to existing tables
• ALTER TABLE allows to add column check constraints as part of definition of
column which is added:
ALTER TABLE <table_name> ADD COLUMN <symbol> <col definition>
[CONSTRAINT [symbol]] CHECK (condition) [[NOT] ENFORCED]
• ALTER TABLE supports addition of table check constraints with syntax:
ALTER TABLE <table_name>
ADD [CONSTRAINT [symbol]] CHECK (condition) [[NOT] ENFORCED]
12. When Check Constraints are Evaluated?
• For DML statements that insert or modify data:
– INSERT
– UPDATE
– REPLACE
– LOAD DATA/XML
• For some of DDL statements:
– CREATE TABLE … SELECT
– ALTER TABLE
13. How Check Constraints are Evaluated?
• For each row
• Constraints in NOT ENFORCED state are skipped
• Constraint violation is reported as error
• With IGNORE clause in DML statements that error becomes a
warning and offending row is skipped
• Evaluation happens after execution of BEFORE triggers but before
passing row to storage engine
15. Check Constraint Expressions
Permitted constructs
•
References to base and generated columns
•
Literals, operators and deterministic built-in
functions (ABS(), LENGTH(), TIMEDIFF(),
ISNULL(),...)
Prohibited constructs
• AUTO_INCREMENT columns
• Non-deterministic and set functions
(RAND(), AVG(),...)
• Sub-queries
• Environment variables (CURRENT_USER,
CURRENT_TIME,…)
• System, user and stored program variables
• Stored functions and UDFs
• Implicit type conversion occurs if operand types mismatch
• Expressions are kept always valid by prohibiting renaming and dropping of participating
columns (auto-dropping constraints with single column reference being exception)
16. Altering Check Constraints
ALTER TABLE clauses to change check constraint enforcement state:
ALTER TABLE <table_name> ALTER CHECK symbol [NOT] ENFORCED
– Supported since 8.0.16
– Non-standard
– Applies to check constraints only
ALTER TABLE <table_name> ALTER CONSTRAINT symbol [NOT] ENFORCED
– Supported since 8.0.19
– Standard
– In future might apply to other constraint types
17. Dropping Check Constraints
ALTER TABLE clauses to drop check constraints:
ALTER TABLE <table_name> DROP CHECK symbol
– Supported since 8.0.16
– Non-standard
– Applies to check constraints only
ALTER TABLE <table_name> DROP CONSTRAINT symbol
– Supported since 8.0.19
– Standard
– Also applies to other constraint types (emits error in case ambiguity)
Also dropping column automatically drops constraint if its condition references
that and only that column.
18. Check Constraints in INFORMATION_SCHEMA
New table - INFORMATION_SCHEMA.CHECK_CONSTRAINTS
Rows for Check Constraints in existing INFORMATION_SCHEMA.TABLE_CONSTRAINTS
19. More Information on Check Constraints
MySQL documentation on check constraints:
https://dev.mysql.com/doc/refman/8.0/en/create-table-check-constraints.html
Blogpost on check constraint:
https://mysqlserverteam.com/mysql-8-0-16-introducing-check-constraint/
MySQL documentation on CREATE TABLE and ALTER TABLE syntax:
https://dev.mysql.com/doc/refman/8.0/en/create-table.html
https://dev.mysql.com/doc/refman/8.0/en/alter-table.html
MySQL documentation on INFORMATION_SCHEMA tables:
https://dev.mysql.com/doc/refman/8.0/en/check-constraints-table.html
https://dev.mysql.com/doc/refman/8.0/en/table-constraints-table.html
MySQL documentation on SHOW table:
https://dev.mysql.com/doc/refman/8.0/en/show-create-table.html