MySQL的复合数据类型:ENUM和SET
来源:SegmentFault
2023-02-24 17:48:11
0浏览
收藏
亲爱的编程学习爱好者,如果你点开了这篇文章,说明你对《MySQL的复合数据类型:ENUM和SET》很感兴趣。本篇文章就来给大家详细解析一下,主要介绍一下MySQL、数据类型、枚举类型、set、enum,希望所有认真读完的童鞋们,都有实质性的提高。
MySQL的常用数据类型包括:
Number/Date/String,而
String类型中又包含了
Char/Varchar/Binary/blob/text等长度不同的简单数据类型,有时我们需要对数据做更细致的管理,比如枚举和集合,就需要复合类型
ENUM和
SET了。
ENUM
枚举类型
ENUM适合于只能在一组固定值中选一个的场景,比如性别只能为男或者女。
ENUM的优势在于:
- 只能在固定值中选择,可以在数据库层面限制非法值。
- 数据的存储用数字来存储,占用空间少。
但是它的使用有很多需要我们注意的地方,一不小心你就会得到错误的结果。
使用ENUM
枚举类型
mysql> create table test (name varchar(40), sex enum('male', 'female') );
mysql> insert into test (name, sex) values('a', 'male'), ('b', 'female'), ('c', 'male');
mysql> select * from test;
+------+--------+
| name | sex |
+------+--------+
| a | male |
| b | female |
| c | male |
+------+--------+
3 rows in set (0.00 sec)创建枚举类型时,我们使用关键字
enum,同时跟着一组可枚举值列表,这些可枚举值必须使用字符串的格式,否则会报错。如果插入值的大小写不匹配,会自动转换成枚举值。
ENUM
类型数据存储的实际值是索引值
我们所有枚举值都是按照枚举值列表中的索引值进行存储的,如上面的
ENUM('male', 'female')的sex字段所有值为:
| 字面值 | 存储值 |
|---|---|
| NULL | NULL |
| '' | 0 |
| 'male' | 1 |
| 'female' | 2 |
因此如果有
1000条记录都存储为
male,我们可能认为数据库存储了
4000个字符,其实只存储了
1000个
1字符。而在查询的时候又会将这个编码过的数字转为实际的值。
我们可以用两个例子测试下:
mysql> select * from test where sex=1; +------+------+ | name | sex | +------+------+ | a | male | | c | male | +------+------+ 2 rows in set (0.00 sec) mysql> select name, sex+0 from test; +------+-------+ | name | sex+0 | +------+-------+ | a | 1 | | b | 2 | | c | 1 | +------+-------+ 3 rows in set (0.00 sec)
这种存储和查询的方式会导致一些处理数字的函数,也会使用存储的值来进行计算,如
SUM()和
AVG():
mysql> select name, avg(sex) from test; +------+--------------------+ | name | avg(sex) | +------+--------------------+ | a | 1.3333333333333333 | +------+--------------------+ 1 row in set (0.00 sec)
读写时不要使用数字
由于上面介绍的用索引值存储的特性,我们不要用枚举类型来存储数字格式的列,否则会引起很大的混淆,如:
mysql> create table test2 (numbers enum('0', '1', '2'));
Query OK, 0 rows affected (0.04 sec)
# 此时2被当做索引值,因此是'1';'2'就是'2';'3'因为不是合法值,会用索引值尝试,因此是'2'
mysql> insert into test2 (numbers) values (2), ('2'), ('3');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from test2;
+---------+
| numbers |
+---------+
| 1 |
| 2 |
| 2 |
+---------+
3 rows in set (0.00 sec)枚举类型的默认值
即便一列被设定为枚举类型,但依然有额外两种值为合法值:
NULL和
''。
当我们插入一个非法值时,在宽松模式下,会插入一个普通的空字符
'',其值为
0。而在严格模式下会报错。
当该字段设定为允许为空时,
NULL字段可以被正常插入。当不允许为空时,如果你不填值,会使用默认值:枚举值的第一个,如上面的
male。
除了设置为严格模式,否则没有合适的办法让一列数据必须插入合法枚举值。使用默认值很多情况下不能满足需求。
枚举类型的排序
常规使用
order by进行排序时,会按照字母的文本顺序。但枚举类型由于存储为索引值,因此会按照索引值进行排序:
NULL 。<p>如果希望按照文本类型进行排序,可以使用:</p><p></p><pre class="brush:go;">order by cast(col as char) 或者 order by concat(col)
枚举值声明的限制
创建数据类型时,枚举值不允许为表达式,如:
mysql> create table test (name varchar(40), sex enum('male', concat('fem', 'ale') );
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'concat('fem', 'ale') )' at line 1枚举值数量的限制
枚举值用
1-2个字节来存储,因此上限值为
2^16-1=65535。
SET
集合类型
SET和
ENUM类型非常相似,它适合于只能在一组固定值中选零个或多个的场景,比如一个人喜欢的颜色可以为红、黄、蓝等颜色中的一个或多个,也可以都不喜欢。
SET的优势和
ENUM也相似,在于:
- 只能在固定值中选择,可以在数据库层面限制非法值。
- 数据的存储用数字来存储,占用空间少。但在枚举值数量很多,而枚举值字符数少时这一可能不成立。
使用SET
枚举类型
mysql> create table test2 (name varchar(40), color set('red', 'green', 'blue', 'yellow'));
Query OK, 0 rows affected (0.04 sec)
mysql> insert into test2(name,color) values ('a', 'red'), ('b', 'red,green'), ('c', 'green,blue,yellow');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from test2;
+------+-------------------+
| name | color |
+------+-------------------+
| a | red |
| b | red,green |
| c | green,blue,yellow |
+------+-------------------+
3 rows in set (0.00 sec)创建时,我们使用关键字
set,同时跟着一组可枚举值列表,这些可枚举值必须使用字符串的格式,否则会报错。
SET
类型数据存储的实际值是索引值的和
我们所有枚举值都是按照列表中的索引值进行存储的,不同的是通过设置二进制数为
1的位置,即
2的幂次方。如上面的
SET('red', 'blue', 'green', 'yellow')的color字段所有值为:
| 枚举值 | 二进制值 | 十进制数字 |
|---|---|---|
| red | 0001 | 1 |
| green | 0010 | 2 |
| blue | 0100 | 4 |
| yellow | 1000 | 8 |
而当有多个值时,通过所有值的求和得到存储的值。因此存储的数据量变少了,当取出的时候编码过的数字又会被转义成实际的字符串。
我们可以用两个例子测试下:
mysql> select name,color+0 from test2; +------+---------+ | name | color+0 | +------+---------+ | a | 1 | | b | 3 | | c | 14 | +------+---------+ 3 rows in set (0.00 sec) mysql> select name,color from test2 where color=14; +------+-------------------+ | name | color | +------+-------------------+ | c | green,blue,yellow | +------+-------------------+ 1 row in set (0.00 sec)
这种存储和查询的方式会导致一些处理数字的函数,也会使用存储的值来进行计算,如
SUM()和
AVG():
mysql> select avg(color) from test2; +------------+ | avg(color) | +------------+ | 6 | +------------+ 1 row in set (0.00 sec)
插入时的顺序和次数
当插入值时,
set类型不关注你插入的顺序和一个枚举值的插入次数,它会自动去重并进行求和得到值,等到取出时,会按照声明的顺序返回:
mysql> insert into test2(name,color) values ('d', 'yellow,green,red,yellow');
Query OK, 1 row affected (0.00 sec)
mysql> select name,color from test2;
+------+-------------------+
| name | color |
+------+-------------------+
| d | red,green,yellow |
+------+-------------------+
4 rows in set (0.00 sec)查找集合值
由于
set类型的特殊性,因此有专用的查找函数:
mysql> select * from test2 where find_in_set('red', color);
+------+------------------+
| name | color |
+------+------------------+
| a | red |
| b | red,green |
| d | red,green,yellow |
+------+------------------+
3 rows in set (0.00 sec)
# 这一种方法当出现lightred颜色的时候就无法正确工作了
mysql> select * from test2 where color like '%red%';
+------+------------------+
| name | color |
+------+------------------+
| a | red |
| b | red,green |
| d | red,green,yellow |
+------+------------------+
3 rows in set (0.00 sec)集合值的计算方式是位运算
前面说是对枚举值去重并自动求和只是为了方便理解,实际上是进行位运算,得到最终的值,如
0001 + 0100 = 0101。
因此我们也可以用类似的方法来查找值:
mysql> select name,color from test2 where color & 10; +------+-------------------+ | name | color | +------+-------------------+ | b | red,green | | c | green,blue,yellow | | d | red,green,yellow | +------+-------------------+ 3 rows in set (0.00 sec) mysql> select name,color from test2 where color & 12; +------+-------------------+ | name | color | +------+-------------------+ | c | green,blue,yellow | | d | red,green,yellow | +------+-------------------+ 2 rows in set (0.00 sec)
上面的这个
&符号什么含义我没查到,但我猜测这个
&符号的含义就是位运算,当两个数在一个位置都为
1时返回
true,如果没有一个位置两者都为
1则为
false。
具体的可以计算下:
a,b,c,d分别为
0001,0011,1110,1011,此时
10为
1010,
12为
1100,当
& 10时,也就是只需要第1位或第3位存在1时(为真)就算匹配成功,从第1位到第4位(高位到低位)分别是
yellow,blue,green,red,所以这个语句类似于
select name,color from test2 where find_in_set('yellow', color) or find_in_set('green', color);可以计算的到上面的结果,其他数字的结果也都符合。
枚举类型的排序
常规使用
order by进行排序时,会按照字母的文本顺序。但枚举类型由于存储为索引值,因此会按照索引值进行排序:
NULL 。<p>如果希望按照文本类型进行排序,可以使用:</p><p></p><pre class="brush:go;">order by cast(col as char) 或者 order by concat(col)
枚举值数量的限制
枚举值用
1-8个字节来存储,因此上限值为
8*8=64个。
参考资料
- 11.4.4 The ENUM Type:https://dev.mysql.com/doc/ref...
- 11.8 Data Type Storage Requirements:https://dev.mysql.com/doc/ref...
- 11.4.5 The SET Type:https://dev.mysql.com/doc/ref...
以上就是《MySQL的复合数据类型:ENUM和SET》的详细内容,更多关于mysql的资料请关注golang学习网公众号!
版本声明
本文转载于:SegmentFault 如有侵犯,请联系study_golang@163.com删除
电竞DOTA2联赛数据api示例代码
- 上一篇
- 电竞DOTA2联赛数据api示例代码
- 下一篇
- MYSQL 索引碎碎念
查看更多
最新文章
-
- 数据库 · MySQL | 1天前 |
- MySQL数值函数大全及使用技巧
- 117浏览 收藏
-
- 数据库 · MySQL | 3天前 |
- 三种登录MySQL方法详解
- 411浏览 收藏
-
- 数据库 · MySQL | 3天前 |
- MySQL数据备份方法与工具推荐
- 420浏览 收藏
-
- 数据库 · MySQL | 3天前 |
- MySQL数据备份方法与工具推荐
- 264浏览 收藏
-
- 数据库 · MySQL | 4天前 |
- MySQL索引的作用是什么?
- 266浏览 收藏
-
- 数据库 · MySQL | 5天前 |
- MySQL排序原理与实战应用
- 392浏览 收藏
-
- 数据库 · MySQL | 1星期前 |
- MySQLwhere条件查询技巧
- 333浏览 收藏
-
- 数据库 · MySQL | 1星期前 |
- MySQL常用数据类型有哪些?怎么选更合适?
- 234浏览 收藏
-
- 数据库 · MySQL | 1星期前 |
- MySQL常用命令大全管理员必学30条
- 448浏览 收藏
-
- 数据库 · MySQL | 1星期前 |
- MySQL高效批量插入数据方法大全
- 416浏览 收藏
-
- 数据库 · MySQL | 1星期前 |
- MySQL性能优化技巧大全
- 225浏览 收藏
-
- 数据库 · MySQL | 1星期前 |
- MySQL数据备份4种方法保障安全
- 145浏览 收藏
查看更多
课程推荐
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
查看更多
AI推荐
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3176次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3388次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3417次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4522次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 3796次使用
查看更多
相关文章
-
- golang MySQL实现对数据库表存储获取操作示例
- 2022-12-22 499浏览
-
- 搞一个自娱自乐的博客(二) 架构搭建
- 2023-02-16 244浏览
-
- B-Tree、B+Tree以及B-link Tree
- 2023-01-19 235浏览
-
- mysql面试题
- 2023-01-17 157浏览
-
- MySQL数据表简单查询
- 2023-01-10 101浏览

