【MySQL】数据类型

文章目录

  • [1. 数据类型的分类](#1. 数据类型的分类)
  • [2. 数值类型](#2. 数值类型)
    • [2.1 tinyint类型](#2.1 tinyint类型)
    • [2.2 bit类型](#2.2 bit类型)
    • [2.3 float类型](#2.3 float类型)
    • [2.4 decimal类型](#2.4 decimal类型)
  • [3. 字符串类型](#3. 字符串类型)
    • [3.1 char类型](#3.1 char类型)
    • [3.2 varchar类型](#3.2 varchar类型)
    • [3.3 char和varchar比较](#3.3 char和varchar比较)
  • [4. 时间日期类型](#4. 时间日期类型)
  • [5. enum和set类型](#5. enum和set类型)

1. 数据类型的分类

MySQL数据类型的作用:

  • 决定了存储数据时应该开辟的空间大小。
  • 决定了如何识别一个特定的二进制序列。
  • 决定了数据的取值范围。

对于数据类型分类,这里简单分为数值类型(入BIT,BOOL,INT),文本,二进制类型(如CHAR、VARCHAR),时间日期(DATE),String类(入ENUM类型)。

2. 数值类型

不同的类型所占字节数都是不一样的,如TINYINT所占字节数为1,而INT所占字节数为4,同时数值范围也是有区别,这些都需要我们去注意。

2.1 tinyint类型

有符号tinyint范围测试

创建一个表,表当中包含一个tinyiny类型的列,默认其为有符号类型。

由于tinyint类型占用1字节,因此有符号tinyint的取值范围为 -128~127,插入该范围内的数据时都能插入成功。

如果插入的数据不在-128~127的范围内,那么插入数据时就会产生保错。

无符号tinyiny范围测试

创建一个表,表当中包含一个tinyiny类型的列,并指定其为无符号类型。

如果插入的数据不在0~255范围时,会报错。

对于MySQL,如果我们插入不合法的数据,MySQL一般都是直接拦截,而不是像C语言那样去截断数据。

反过来,我们如果已经有数据被插入到MySQL了,一定是插入的合法的数据。

所以MySQL中,数据类型本身也是一种约束,约束程序员尽可能地进行正确地插入,约束使用者,如果你不是一个很好的使用者,MySQL也能保证数据插入的合法性。

用时,我们还是尽量不适用unsigned。比如,对于int类型存不下的数据,int unsigned同样存不下,与其如此,还不如在设计时,将int类型提升为bigint类型。

2.2 bit类型

bit类型的显示方式

创建一个表,表当中包含一个int类型的id列和一个8位bit类型的a列。

向表中插入一条记录,记录中指定id和a的值均为10,插入记录后查看表会发现a的值显示的并不是10。

根本原因是因为bit类型在显示时,是按照ASCII码对应的值进行显示的,而在ASCII码表中10对应的是控制字符LF,表示换行的意思。如果向表中插入记录时指定id和a的值均为65,由于ASCII码表中65对应的是字符A,因此插入记录后查看表就会发现a的值为A。

  • 虽然MySQL提供了位类型bit,但一般不建议将数据类型设置为位类型,除非将来这个数据本身就是只给程序看的,并且数据本身非常占用资源。
  • 因为查询位类型数据时,如果使用了位类型bit,默认会按照ASCII码对应的值进行显示,这对于将来数据库管理员维护数据库或程序员调试程序都是不太方便的。

2.3 float类型

float[(m, d)] [unsigned] : M指定显示长度,d指定小数位数,占用空间4个字节

举个例子

此时要求浮点数小数位数是两位。

如果插入得到是23.456,那么会四舍五入为23.46。

如果插入99.995那就不允许了,因为这个数在四舍五入之后是不合法的。

总结一下就是:float(4,2)表示的范围是-99.99 ~ 99.99,MySQL在保持值时会进行四舍五入,所以实际可插入的范围为-99.994 ~ 99.994。

而如果是无符号float类型得到取值范围,实际就是把对应有符号float类型中的负数部分全部拿走了,因此float(4,2)的取值范围为0 ~ 99.99,实际可插入的范围为0 ~ 99.994。

2.4 decimal类型

decimal的精度更高

decimal和float类型的使用方式一样,但decimal的精度比float跟高。

创建一个表,表当中分别包含一个float(10,8)的列和一个decimal(10,8)的列。

向表中插入一条记录,指定float和decimal的值均为23.12345612,但最终查表时发现decimal保持了数据的原貌,而float则会存在一定的精度损失。

3. 字符串类型

3.1 char类型

char(L): 固定长度字符串,L是可以存储的长度,单位为字符,最大长度值可以为255

如果插入汉字,对于gbk编码一个占用2个字节,utf8编码一个汉字占用3个字节。

而我们这里插入两个汉字能够成功,这说明对于char单位为字符,mysql的字符与C/C++语言不同,mysql的字符代表的是符号,所以能够插入成功。

总结就是char(2)表示可以存放两个字符,可以是字母或者汉字,但是不能超过两个。而char()括号内的值最多只能是255。

3.2 varchar类型

varchar(L): 可变长度字符串,L表示字符长度,最大长度65535个字节(mysql存储char类型,utf8默认是3字节,65535/3 = 21845)

举个例子

varchar类型最多占用65535字节,其中有1 ~ 2 的字节用于表示实际数据长度,还有1字节来存储其他控制信息,因此varchar类型的有效字节数为65532字节。

而varchar类型可指定的字符个数上限,与表的编码格式有关:

  • 对于utf8编码来说,一个字符占用三个字节,因此varchar(L)中的L最大可知道为 65532 / 3 = 21844。
  • 对于gbk编码来说,一个字符占用两个字节,因此varchar(L)中的L最大可指定为 65532 / 2 = 32766。

因此在定义编码格式为utf8的表时,varchar(L)中的L如果超过了21844,则会产生报错。

而在定义编码格式为gbk的表时,varchar(L)中的L如果超过了32766,则会产生报错。

3.3 char和varchar比较

char和varchar比较

char和varchar比较如下:

  • char类型可存储字符上限为255,varchar类型可存储字符上限与表的编码格式有关。
  • char(L)定义后,无论存储的字符串长度是否到达L,都会开辟用于存储L个字符的定长空间,如果存储的字符串长度超过L则会保错。
  • varchar(L)定义后,会根据存储字符串的长度按需开辟空间,并且需要使用1 ~ 3字节的空间用于表示存储字符串以及其他控制信息,如果存储的字符串超过L则会报错。

如何选取char和varchar?

char和varchar的优缺点如下:

  • char类型的数据是定长的,因此磁盘空间比较浪费,但是效率高(直接访问定长空间)。
  • varchar类型的数据是变长的,因此磁盘空间比较节省,但是效率低(需要先读取存储字符串的长度,再访问指定长度的空间)。

需要要存储的数据是定长的,那么就使用char类型进行存储,比如身份证号码、手机号等。如果要存储的数据是变长的,那么就使用varchar类型进行存储,比如名字、地址等。

4. 时间日期类型

三种时间日期类型

常用的三种时间日期类型如下:

  • date:日期格式为YYYY-MM-DD,占用三字节。
  • datetime:时间日期格式为YYYY-MM-DD HH:MM:SS,占用八字节。
  • timestamp:时间戳,格式为YYYY-MM-DD HH:MM:SS,占用四字节。

创建一个表,表当中包含date、datetime和timestamp三种时间日期类型的列。

查看表结构可以看到,timestamp类型的t3列是不允许为空的,它的默认值为CURRENT_TIMESTAMP。

因此如果插入数据时不插入t3列,那么就会自动插入当前的时间戳。

timestamp的使用

创建一个评论表,表当中包含评论人的昵称、评论的内容和评论的发布时间。

向评论表中插入记录时,只需要指明评论人的昵称和评论的内容,评论的发布时间默认就会设置成该记录的插入时间。

如果评论人修改了评论内容,那么就需要对其评论表进行更新,更新表的同时评论的发布时间也会更新为修改表的时间。

5. enum和set类型

enum和set类型

enum和set的类型区别如下:

  • 在定义enum字段时需要提供若干个选项的值,在设置enum字段值时只允许选取其中的一个值。
  • 在定义set字段时需要提供若干个选项的值,在设置set字段值时可以选取其中的一个或多个值。

比如人的性别只能从男和女中进行二选一,因此可以定义成enum类型,而人的爱好在提供的选项中可能存在多个,因此可以定义成set类型。

调查表案例

创建一个调查表,表中包含被调查人的姓名、性别和爱好。

向表中插入记录时,被调查人的性别只能从男和女中进行二选一,被调查人的爱好可以从提供的若干个选项中进行多选一或者多选多,多个爱好直接需要通过英文逗号隔开。

通过数字设置num

在插入记录时,除了通过指明男女来设置性别,还可以通过插入数字1和2来设置性别。

根本原因在于,MySQL处于效率考虑,在存储enum值时实际存储的都是数字,enum中提供的选项值依次对应数字1、2、3 ... 最多65515个。因此在设置enum值时可以通过数字的方式进行设置。

通过数字设置set

在插入记录时,除了通过指明多个选项来设置爱好,还可以通过数字的方式来设置。

因为MySQL存储set值时实际存储的也是数字,set中提供的选项值依次对应数字1、2、4、8、...,最多64个,因此在设置set值时可以通过数字的方式进行设置。

注意:

  • 虽然enum和set可以通过数字的方式进行设置,但强烈不推荐这种做法,因为这样的SQL可读性太差,导致后期维护成本变高。

enum和set查找

如果想要筛选出调查表中所有女同志的信息,那么直接在筛选时指明 gender='女' 即可,因为enum类型的值只能多选一。

但如果要筛选出调查表中爱好写代码的人的信息就比较麻烦了,如果继续使用上述方式,那么最终筛选出来的是爱好仅为写代码的人的信息。

这时就需要借助 find_in_set(str, strlist) 函数,该函数的作用是查询strlist中是否包含str,如果包含则返回str在strlist中的位置(从1开始),否则返回0。

通过select可以对 find_in_set 函数进行验证,依此查找集合a,b,c中是否包含字符a、b、d,这时在查找字符a和b时就会得到其在集合的下标,而在查找字符d时就会得到0值。

这时就可以通过select搭配 find_in_set 函数,来筛选出爱好包含写代码的人的信息了。

相关推荐
武子康1 小时前
大数据-231 离线数仓 - DWS 层、ADS 层的创建 Hive 执行脚本
java·大数据·数据仓库·hive·hadoop·mysql
黑色叉腰丶大魔王1 小时前
《MySQL 数据库备份与恢复》
mysql
Ljw...1 小时前
索引(MySQL)
数据库·mysql·索引
OpsEye2 小时前
MySQL 8.0.40版本自动升级异常的预警提示
数据库·mysql·数据库升级
Ljw...2 小时前
表的增删改查(MySQL)
数据库·后端·mysql·表的增删查改
i道i9 小时前
MySQL win安装 和 pymysql使用示例
数据库·mysql
Oak Zhang10 小时前
sharding-jdbc自定义分片算法,表对应关系存储在mysql中,缓存到redis或者本地
redis·mysql·缓存
久醉不在酒12 小时前
MySQL数据库运维及集群搭建
运维·数据库·mysql
WindFutrue12 小时前
使用Mybatis向Mysql中的插入Point类型的数据全方位解析
数据库·mysql·mybatis
一只爱撸猫的程序猿13 小时前
一个简单的Linux 服务器性能优化案例
linux·mysql·nginx