在mysql8.0之前,mysql仅仅只在语法上支持check约束,实际过程中会被数据库忽略,这也许是因为大佬在设计check约束的时候考虑到,更改数据库时,进行这种约束检查很耗费性能,所以有意将此种需求甩给了业务端的程序员来处理。如果我们非得在数据库层进行约束控制,可以参考本篇文章。
CHECK 检查约束
在我们使用 MySQL 插入数据时,假如我们插入性别,就只能插入‘男’、‘女’,或者插入数据控制在一定范围内,我们都会使用 CHECK 检查约束来实现。
问题:
MySQL 所有的存储引擎都不支持 CHECK 约束,MySQL中可以写 CHECK 约束,但会忽略它的作用,因此 CHECK 并不起作用,因此实现对数据约束有两种方法:
- 在 MySQL 种约束,如使用 ENUM 类型 或者 触发器 。
- 在应用程序里面对数据进行检查再插入。
在这里我们主要解释第一种的 ENUM 类型或者触发器如何实现 CHECK约束作用;
ENUM 控制选项:
具体用法讲解可参考 MySQl 数据类型 ENUM
CREATE TABLE person(
id tinyint(4) NOT NULL AUTO_INCREMENT,
name varchar(16) NOT NULL,
sex enum('男','女') NOT NULL
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO person(name, sex) VALUES('luchi1','男');
INSERT INTO person(name, sex) VALUES('luchi2','女');
INSERT INTO person(name, sex) VALUES('luchi3','中');
如图所示,sex 只能插入男,女;
触发器控制范围:
在这里我们把表加上一个字段年龄
ALTER TABLE person ADD age tinyint(4) NOT NULL;
创建触发器,控制当年龄 <0 或者 >120 时不能插入:
DELIMITER $$
CREATE TRIGGER before_age_insert
BEFORE INSERT
ON person FOR EACH ROW
BEGIN
IF (NEW.age < 0 OR NEW.age>120) THEN
DELETE FROM person WHERE age = NEW.age;
END IF;
END$$
DELIMITER ;
测试:
TRUNCATE TABLE person; --清空表
INSERT INTO person(name, sex, age) VALUES('luchi1','男','21');
INSERT INTO person(name, sex, age) VALUES('luchi2','女','121');
会发现当插入数据不符合数据范围时插入不会成功;