(一) 数据类型特点
1) 数据类型占用的存储空间与分类
英文名称 |
中文名称 |
分类 |
存储范围 |
存储空间 |
ENUM |
枚举类型 |
字符类型 |
1~65535个元数据 |
1个字节 或 2个字节 |
SET |
集合类型 |
1~64个元数据 |
1,2,3,4 或 8个字节 |
|
BOOL/BOOLEAN |
布尔类型 |
数值类型 |
-128~127 或 0~255 |
1个字节 |
TINYINT |
微整型 |
-128~127 或 0~255 |
1个字节 |
上述表格传递的信息:
(1). 四种数据类型的存储范围是所属分类中较小或最小数据类型;
(2). ENUM、SET属于字符串类型;
(3). BOOL/BOOLEAN、TINYINT属于数值类型;
(4). BOOL/BOOLEAN与TINYINT的存储空间范围相同,所占存储空间也相同;
3) 数据类型的其他信息
(1). ENUM
a) 枚举类型ENUM字段定义的值域列表中,元素的数量最大不能超过65535;
b) 枚举类型ENUM字段的每个元素值,可以为数字、字母、特殊符号等,必须用一对单引号或一对双引号括起来;
c) 枚举类型ENUM字段的每个元素值必须为常量值,不允许使用变量、任何函数或表达式;
d) 枚举类型ENUM字段定义的值域列表中,不允许显示出现NULL值;
e) 枚举类型ENUM字段存储的值,允许为NULL,且NULL值的序列编号为NULL;
f) 枚举类型ENUM字段定义为非NULL时,则定义语法中默认关键字指定的值,也必须为枚举类型ENUM字段定义的值域列表中存在的值;
g) 枚举类型ENUM字段定义为非NULL时,字段无指定的值写入,若是有显示申明的默认值时,采用默认关键字指定的值;若字段定义无指定默认关键的时,则使用枚举类型ENUM字段定义的值域列表中第一个元素作为默认值;
h) 枚举类型ENUM字段定义没有显式申明为非NULL时,则默认是值为NULL;
i) 集合类型SET字段写入一个值域列表中不存在的值,则会默认用空格值替代,序列编号为0,并提示一个警告信息(注释:也跟sql_mode模式有关,严格的模式则会转变为出错,而不是警告提示);
(2). SET
a) 集合类型SET字段的值域列表中,元素的数量最大不能超过64;
b) 集合类型SET字段的每个元素,可以为数字、字母、特殊符号等,必须用一对单引号或一对双引号括起来,也即必须为字符类型的值,也即不管是字符串还是数字;
c) 集合类型SET字段的每个元素值必须为常量值,不允许使用变量、任何函数或表达式;
d) 集合类型SET字段定义的值域列表中,不允许显示出现NULL值;
e) 集合类型SET字段存储的值,允许为NULL,且NULL值的序列编号为NULL;
f) 集合类型SET字段定义为非NULL时,则定义语法中默认关键字指定的值,也必须为集合类型SET字段定义的值域列表中存在的值;
g) 集合类型SET字段定义为非NULL时,字段无指定的值写入,若是有显示申明的默认值时,采用默认关键字指定的值;若字段定义无显式申明默认值时,则使用空字符串作为默认值,并且会给出一个字段值阶段的警告信息;
h) 集合类型SET字段定义没有显式申明为非NULL时,则默认是值为NULL;
i) 集合类型SET字段写入一个元素列表中无法组合的集合值,则会默认用空格值替代,序列编号为0,并提示一个警告信息(注释:也跟sql_mode模式有关,严格的模式则会转变为出错,而不是警告提示);;
(3). BOOL/BOOLEAN
a) 布尔类型的关键可以写成BOOL,或者BOOLEAN,都是正确写法;
b) 布尔类型BOOL/BOOLEAN字段的值,必须为整型或者为(TRUE,FALSE),否则出现截断;
c) 布尔类型BOOL/BOOLEAN等同于TINYINT(1),只是使用其中低位存储值,其他存储位都置0的做法,而且0为FALSE,非0值则为TRUE,后续讲解的数据类型测试会佐证上述信息;
d) 若向布尔类型BOOL/BOOLEAN字段,存储一个非0/1,也非TRUE/FALSE的值,不会出现转换,而是存储你所填写的真实值;
e) 若是向布尔类型BOOL/BOOLEAN字段,存储一个超过其存储范围-128—127或0—255之间的值,会出现截断并用最大(注释:正整数则是最大)或最小的值替换(注释:负整数则是最小);
备注:
实际使用过程中,我们会发现执行表创建命令之后,发现BOOL/BOOLEAN字段的数据类型默认被转换成TINYINT(1),也不能显式存储TRUE或FALSE,而是用1或0替换。
(4). TINYINT
整型一共有五种:TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,其中TINYINT属于整型类型中最小的,存储的值必须为整型的数值,否则会被默认转换或报错(注:取决于MySQL运行时设置的SQL_MODE值要求);
MySQL数据库的布尔类型BOOL或称布尔类型BOOLEAN,等同于微整型TINYINT(1)。MySQL数据库数据类型分类中确实存在布尔类型,但是MySQL数据库并没有真正实现布尔类型,而是借助微整型的方式实现,并且创建数据库表结构的时候,即使字段定义属性设置为布尔类型BOOL或布尔类型BOOLEAN,都会被默认改写成TINYINT(1)。
MySQL数据库产品没有真正实现对布尔类型的支持,建议大家不要使用MySQL布尔类型BOOL或布尔类型BOOLEAN,而是使用数据库类型微整型TINYINT替代。
(2). 枚举类型ENUM
优点
1) MySQL枚举类型的枚举元素允许最大65535个,基本够绝大多数业务场景使用;
2) 引入枚举类型数据存储,有利于缩减数据库存储数据的容量,尤其能达到减少数据库瓶颈最大的物理IO,逻辑IO也能减小,提高主机的处理能力;
3) 引入枚举类型数据存储,有利于简化工程师的代码复杂度、工作量,增加代码的可读性和可维护性;
4) 可以通过枚举类型元素值访问数据,也可以根据枚举类型元素编号进行访问数据;
l 缺点
1) MySQL数据库枚举类型的引入,可能给软件程序的版本发布,存在遗忘数据库结构变更的隐患;
2) MySQL数据库枚举类型字段的元素增加,必须以尾部追加的方式,否则影响数据库提供数据服务;
3) 枚举类型字段不再需要的元素,也不能进行删除,否则影响数据库提供数据服务;
4) MySQL数据库枚举类型的字段定义属性元素值,不能随意调整其顺序,否则影响数据库提供数据服务;
建议:
MySQL数据库枚举类型是一种有应用场景广泛的数据类型,若是抛开网站程序或软件版本发布,可能会导致开发工程师与数据库维护人员之间没有配合好的问题,非常推荐大家把枚举类型引入到生产环境的数据库应用中,对企业而言也可以起到节省人力、物理等成本。建议大家使用枚举类型的时候,尽量把可能需要用到的枚举元素,都写到MySQL数据库表字段的定义属性中,减少出现漏做DDL变更的故障。
(3). 集合类型SET
优点
1) 数据库的数据存储容量相应缩小,利于减少数据操纵的逻辑IO和物理IO;
2) 集合类型的数据读取方便,可根据字符串值,也可以根据字符串集合的顺序编号;
3) 集合类型字段的定义属性维护与其他数据类型类似,并不特殊化;
4) 开发工程师,不需要借助额外的集合元素编码表或程序中使用编号替代集合的字符串元素,达到减少开发成本、提高代码的可读性和可维护性;
l 缺点
1) 集合类型字段的集合元素限制最大为64个;
2) 集合类型字段的定义属性的集合元素,删除导致锁表而影响数据服务提供;
3) 集合类型字段的定义属性的集合元素增加,只能以尾部追加的方式,若是此特性没有掌握,则会导致数据服务提供受影响;
(4). 总结
系统地分析了布尔类型、枚举类型、集合类型,MySQL数据库没有实现布尔类型,只是借助微整型TINYINT(1)间接实现,为此可以理解MySQL数据库没有布尔类型;集合类型与枚举类型,都各自存在一个非常可怕的弊端 — 数据库结构变更没有做,网站程序或软件版本发布已上线,导致用户数据丢失的问题,那么我们不使用枚举类型或集合类型,能否获得这2种数据类型的优点,规避这2种数据类型的缺陷,为此我们各举一个实际应用案例。
若是采用枚举类型存储商品分类信息,我们则可以简便地创建一张表,2个字段即可实现上述的做法,最大的缺陷是子节点升级为父节点的时候,则需要发布网站程序与做数据库结构变更。修改枚举类型字段的定义属性,必须以尾部追加的方式,才不影响数据库提供的数据服务。使用我们介绍的替代办法,则需要工程师编写更多的代码实现,可以借助图形化管理工具轻松完成,各自都有优缺点。
一句话总结:任何解决方案,必须从技术、开发成本、维护成本、可靠性等多个角度综合论证,寻找最适合团队、业务场景的方案。