前言

设计表结构时,你会遇到一些固定选项值的字段。例如,性别字段(Sex),只有男或女;又或者状态字段(State),有效的值为运行、停止、重启等有限状态。大多数开发人员喜欢用 INT 的数字类型去存储性别字段,这种做法有一些弊端:

  • 表达不清:在具体存储时,0 表示女,还是 1 表示女呢?每个业务可能有不同的潜规则;
  • 脏数据:因为是 tinyint,因此除了 0 和 1,用户完全可以插入 2、3、4 这样的数值,最终表中存在无效数据的可能,后期再进行清理,代价就非常大了。

    使用 check 约束功能

    MySQL 8.0.16 版本开始,数据库原生提供 check 约束功能,可以方便地进行有限状态列类型的设计。
    新建一个 user 表,使用 check (sex = 'M' OR sex = 'F')sex 字段进行约束,只允许插入 MF
    1. drop table if exists user;
    2. create table user (
    3. id bigint unsigned auto_increment primary key,
    4. name varchar(10) not null default '' comment '用户名',
    5. sex char(1) not null default '' comment '性别',
    6. check (sex = 'M' OR sex = 'F')
    7. ) comment '用户表';

    测试插入数据

    如果 sex 字段插入合法的值: ```sql mysql> insert into user(name, sex) VALUES (‘username1’, ‘M’); Query OK, 1 row affected (0.02 sec)

mysql> select * from user; +——+—————-+——-+ | id | name | sex | +——+—————-+——-+ | 1 | username1 | M | +——+—————-+——-+ 1 row in set (0.00 sec)

  1. 如果 sex 字段插入非法的值,报错:
  2. ```sql
  3. mysql> insert into user(name, sex) VALUES ('username2', 'G');
  4. ERROR 3819 (HY000): Check constraint 'sex_check' is violated.