社区投稿 | MySQL 8.0.16 开始支持 check 完整性

原创: 蒋乐兴html


做者简介python

蒋乐兴,MySQL DBA,擅长 python 和 SQL ,目前维护着github的两个开源项目:mysqltools 、dbmc以及独立博客:https://www.sqlpy.commysql

 

一直以来MySQL都只实现了实体完整性、域完整性、引用完整性、惟一键约束。git

惟独 check 完整性迟迟没有到来,MySQL 8.0.16(2019-04-25 GA) 版本为这个画上了句号。github

 

1、没有 check 完整性约束会怎样

一、没有 check 完整性约束可能会影响到数据的质量。sql

-- 建立一个 person 表来保存名字,年龄这个两个基本信息
CREATE TABLE person ( NAME VARCHAR ( 16 ), age INT );
-- 这种状况下能够插入一个年龄为 -32 的行,负的年龄明显是没有意义的
INSERT INTO person ( NAME, age )
VALUE
( '张三岁',- 32 );
select * from person;
+-----------+------+
| name | age |
+-----------+------+
| 张三岁 | -32 |
+-----------+------+
1 row in set (0.00 sec)

 

二、若是单单只是不能容忍负值,咱们能够换一种非负整数类型来克服一下。spa

-- 先删除以前的 person 定义
drop table if exists person;
Query OK, 0 rows affected (0.01 sec)
-- 建立一个新的 person 表
create table if not exists person(name varchar(16),age int unsigned);
Query OK, 0 rows affected (0.01 sec)
-- 声明的时候说明了 age 只能是正数,因此插入负数就会报错
insert into person(name,age) value('张三岁',-32);
ERROR 1264 (22003): Out of range value for column 'age' at row 1

上面的这种解决方案其实就是经过域完整性来实现的数据验证,域完整性的能力仍是有边界的。code

好比说,要求age必定要18岁之上它是作不到的,而这种需求正是check完整性大显身手的地方。htm

 

2、看用 check 如何解决

一、MySQL  8.0.16+版本, check 完整性解决age要大于18的问题。ci

select @@version;
+-----------+
| @@version |
+-----------+
| 8.0.16 |
+-----------+
1 row in set (0.00 sec)
-- 先删除以前定义的表
drop table if exists person;
Query OK, 0 rows affected (0.01 sec)
-- 建立新的表,并对 age 列进行验证,要求它必定要大于 18
create table if not exists person(
name varchar(16),
age int,
constraint ck_person_001 check (age > 18) -- 加一个 check 约束条件
);
Query OK, 0 rows affected (0.02 sec)
-- 查看表的定义
show create table person;
+--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| person | CREATE TABLE `person` (
`name` varchar(16) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
CONSTRAINT `ck_person_001` CHECK ((`age` > 18))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
-- 插入的数据若是不能经过 check 约束就会报错
insert into person(name,age) value('张三岁',-32);
ERROR 3819 (HY000): Check constraint 'ck_person_001' is violated.
insert into person(name,age) values('张三岁',17);
ERROR 3819 (HY000): Check constraint 'ck_person_001' is violated.
insert into person(name,age) values('张三岁',19);
Query OK, 1 row affected (0.01 sec)

 

二、MySQL 8.0.16 如下版本的 MySQL 会怎样?

select @@version;
+-----------+
| @@version |
+-----------+
| 8.0.15 |
+-----------+
1 row in set (0.00 sec)
drop table if exists person;
Query OK, 0 rows affected (0.00 sec)
create table if not exists person(
name varchar(16),
age int,
constraint ck_person_001 check (age > 18) -- 加一个 check 约束条件
);
Query OK, 0 rows affected (0.01 sec)
-- 能够看到在低版本下 check 约束被直接无视了,也就是说低版本是没有 check 约束的
show create table person;
+--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| person | CREATE TABLE `person` (
`name` varchar(16) COLLATE utf8mb4_general_ci DEFAULT NULL,
`age` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci |
+--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
--
insert into person(name,age) value('张三岁',-32);
Query OK, 1 row affected (0.00 sec)

 

能够看到在 MySQL 8.0.16 如下的版本中,check直接被忽略。

新版本在CHECK Constraints功能上的完善提升了对非法或不合理数据写入的控制能力。

除了以上示例中的列约束以外,CHECK Constraints还支持表约束。

想要了解更多关于CHECK Constraints 的详细语法规则和注意事项,请参考MySQL官网文档

https://dev.mysql.com/doc/refman/8.0/en/create-table-check-constraints.html

相关文章
相关标签/搜索