力扣刷题的时候碰见枚举类型,我一看,咦,这居然在我的知识库之外。不行,我得把它添加进来。于是我翻遍了资料,终于把它弄明白了。
然而高兴了不到一天,发现它的缺点也是一大堆,甚至还有人文中表明不建议使用。
顿时,我的这个心情,格外复杂。但也不想让自己的精力就这么白白浪费了,就把它放在这里吧。供想学习枚举类型的小伙伴参考参考。
应用场景
如果每条记录的某属性都是在一组固定值中选一个,那么这个属性就可以用枚举类型来进行存储,例如性别只能在男女中选一个。
枚举类型可以规范数据,限定只能插入规定的数据项。
举个例子:
create table gender(
sex enum('male','female') default 'male'
);
-- 创建表gender,其中sex字段的数据类型是枚举类型。
-- 那么在插入数据时,每条记录的sex属性就只能在male和female中选一个。
insert into gender values('男'); -- 报错
insert into gender values('female'); -- 成功,插入一条记录,其sex属性值为female
枚举类型可以节约存储空间。
在上面的例子中,存储时,每条记录的sex属性值存储的不是字符串male和female,而是下标1和2。在某些情况下可以减少存储空间。
一条记录节约一点小小的存储空间,数据量少的时候也许差别不大,但若成千上万条数据呢?
有长必有短,enum也有很多缺点,为避免引起错误,缺点需要格外注意。
语法
-- 创建表时
列名 enum('属性值1','属性值2','属性值3'...)
插入数据
插入数据时既可以插入规定的数据,也可以采用下标的形式插入。
但是如果采用下标类型插入数据的话,要注意下标与属性值得对应关系。
1、插入规定数据
在插入数据时,可以插入创建表时规定的一组数据中的一个。例如:
create table gender(
sex enum('male','female') default 'male'
);
-- 插入数据
insert into gender values('male');
-- 由于mysql对大小写不敏感,以下语句也是可以执行成功的。
insert into gender values('Female');
insert into gender values('MALE');
2、采用下标的形式插入
create table gender(
sex enum('male','female') default 'male'
);
insert into gender(sex) values(1); -- 成功,sex=male
insert into gender values(2); -- 成功,sex=female
-- 采用下标的形式插入数据时,类型限制不严格(string、int类型都可以),以下语句也可以成功执行。
insert into gender values('1');
insert into gender values('2');
查询数据
与插入数据一样,查询数据时也有两种方式。
一种是根据规范数据正常查询。一种是根据下标查询。
-- 数据准备
create table test_order(
order_id char(5) primary key,
user_id char(3),
product_name varchar(50),
price int,
order_state enum('待支付','待发货','运输中','已收货')
);
insert into test_order values
('00001','001','iphone14',6199,1), -- 待支付
('00002','002','华为笔记本',4500,2), -- 待发货
('00003','001','六神花露水',15,2), -- 待发货
('00004','003','小米音箱',299,3), -- 运输中
('00005','002','罗技无线鼠标',35,3), -- 运输中
('00006','004','洗地机',1999,2), -- 待发货
('00007','005','立白洗衣液',69,4), -- 已收货
('00008','005','护手霜',109,2), -- 待发货
('00010','004','蓝月亮洗衣液',68,4); -- 已收货
-- 查询还未发货的订单,提醒卖家发货
-- 根据规定的数据正常查询
select * from test_order where order_state='待发货';
-- 根据下标查询
select * from test_order where order_state=2;
注意:
- 根据规定数据正常查询时,由于mysql对大小写不敏感,所以不区分大小写。
- 根据下标查询时,只能用int类型,不能使用string类型。
修改数据
修改数据同插入数据相似,支持规范数据和下标两种形式。下标可以是int型,也可以是string类型。
-- 编号为00002的订单,卖家已经发货,将其状态修改为运输中
update test_order set order_state=3 where order_id='00002';
缺点
枚举类型可以使用下标来进行操作,但是从上面的例子中,下标似乎是从1开始的?这是因为0具有特殊意义。
create table test_order( order_id char(5) primary key, user_id char(3), product_name varchar(50), price int, order_state enum('待支付','待发货','运输中','已收货') ); -- 这里 待支付-1,待发货-2,运输中-3,已收货-4
上面例子中,如果往enum列中插入无效值,会直接报错。因为目前使用的版本开启了严格模式。
在比较古老的版本中,或者关闭掉严格模式的情形下,如果插入无效值,可以被插入,但是插入的是一个空字符串,这个空字符串的索引为0
第2个要注意的点是:不要使用数字作为枚举值!!!
因为enum类型每条记录存储的是下标,也支持下标进行操作。如果使用数字作为枚举值很容易造成混乱。例如:
enum('5','3','2','1') insert into test values('2'); -- 存储的是枚举值2,还是下标为2的枚举值3?
第3个要注意的点是:枚举值的修改和添加问题。
如果枚举值已经被引用,那么将无法被修改。
例如,尝试把上面例子中的待支付改成待付款。
修改已引用的枚举值(报错)
添加新的枚举值(只能在列表最后添加)
修改未引用的枚举值(成功)
更多关于枚举类型的限制,参考:臭名昭著的 MySQL ENUM 类型 ( 上 ) - MySQL 拾遗 - 简单教程,简单编程