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

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

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


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

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

 
 
  1.   -- 建立一个 person 表来保存名字,年龄这个两个基本信息app

  2.   CREATE TABLE person ( NAME VARCHAR ( 16 ), age INT );ide


  3.   -- 这种状况下能够插入一个年龄为 -32 的行,负的年龄明显是没有意义的spa

  4.   INSERT INTO person ( NAME, age ) code

  5.   VALUEorm

  6.    ( '张三岁',- 32 );htm


  7.   select * from person;ci

  8.   +-----------+------+

  9.   | name      | age  |

  10.   +-----------+------+

  11.   | 张三岁    |  -32 |

  12.   +-----------+------+

  13.   1 row in set (0.00 sec)


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

 
 
  1.   -- 先删除以前的 person 定义

  2.   drop table if exists person;

  3.   Query OK, 0 rows affected (0.01 sec)


  4.   -- 建立一个新的 person

  5.   create table if not exists person(name varchar(16),age int unsigned);

  6.   Query OK, 0 rows affected (0.01 sec)


  7.   -- 声明的时候说明了 age 只能是正数,因此插入负数就会报错

  8.   insert into person(name,age) value('张三岁',-32);

  9.   ERROR 1264 (22003): Out of range value for column 'age' at row 1


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

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


2、看用 check 如何解决

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

 
 
  1.   select @@version;                                                                          

  2.   +-----------+

  3.   | @@version |

  4.   +-----------+

  5.   | 8.0.16    |

  6.   +-----------+

  7.   1 row in set (0.00 sec)


  8.   -- 先删除以前定义的表

  9.   drop table if exists person;

  10.   Query OK, 0 rows affected (0.01 sec)


  11.   -- 建立新的表,并对 age 列进行验证,要求它必定要大于 18

  12.   create table if not exists person(

  13.       name varchar(16),

  14.       age int,

  15.       constraint ck_person_001 check (age > 18) -- 加一个 check 约束条件

  16.   );

  17.   Query OK, 0 rows affected (0.02 sec)


  18.   -- 查看表的定义

  19.   show create table person;                                                                  

  20.   +--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

  21.   | Table  | Create Table                                                                                                                                                                                                  |

  22.   +--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

  23.   | person | CREATE TABLE `person` (

  24.   `name` varchar(16) DEFAULT NULL,

  25.   `age` int(11) DEFAULT NULL,

  26.   CONSTRAINT `ck_person_001` CHECK ((`age` > 18))

  27.   ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |

  28.   +--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+



  29.   1 row in set (0.00 sec)


  30.   -- 插入的数据若是不能经过 check 约束就会报错

  31.   insert into person(name,age) value('张三岁',-32);

  32.   ERROR 3819 (HY000): Check constraint 'ck_person_001' is violated.


  33.   insert into person(name,age) values('张三岁',17);

  34.   ERROR 3819 (HY000): Check constraint 'ck_person_001' is violated.


  35.   insert into person(name,age) values('张三岁',19);

  36.   Query OK, 1 row affected (0.01 sec)


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

 
 
  1.   select @@version;  

  2.   +-----------+

  3.   | @@version |

  4.   +-----------+

  5.   | 8.0.15    |

  6.   +-----------+

  7.   1 row in set (0.00 sec)


  8.   drop table if exists person;

  9.   Query OK, 0 rows affected (0.00 sec)


  10.   create table if not exists person(

  11.       name varchar(16),

  12.       age int,

  13.       constraint ck_person_001 check (age > 18) -- 加一个 check 约束条件

  14.   );

  15.   Query OK, 0 rows affected (0.01 sec)


  16.   -- 能够看到在低版本下 check 约束被直接无视了,也就是说低版本是没有 check 约束的

  17.   show create table person;

  18.   +--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

  19.   | Table  | Create Table                                                                                                                                                                          |

  20.   +--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

  21.   | person | CREATE TABLE `person` (

  22.   `name` varchar(16) COLLATE utf8mb4_general_ci DEFAULT NULL,

  23.   `age` int(11) DEFAULT NULL

  24.   ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci |

  25.   +--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

  26.   1 row in set (0.00 sec)


  27.   --

  28.   insert into person(name,age) value('张三岁',-32);

  29.   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

相关文章
相关标签/搜索