MySQL数据类型

一、数据类型分类

在MySQL中,有下面的这些数据类型:

分类 数据类型 说明
数值类型 BIT(M) 位类型。M 指定位数,默认值 1,范围 1~64
TINYINT UNSIGNED 带符号的范围 - 128~127,无符号范围 0~255。默认有符号
BOOL 使用 0 和 1 表示真和假
SMALLINT UNSIGNED 带符号是−215 到 215−1,无符号是216−1
INT UNSIGNED 带符号是−231 到 231−1,无符号是232−1
BIGINT UNSIGNED 带符号是−263 到 263−1,无符号是264−1
FLOAT(M,D) UNSIGNED M 指定显示长度,d 指定小数位数,占用 4 字节
DOUBLE(M,D) UNSIGNED 表示比 float 精度更大的小数,占用空间 8 字节
DECIMAL(M,D) UNSIGNED 定点数,M 指定长度,D 表示小数点的位数
文本、二进制类型 CHAR(size) 固定长度字符串,最大 255
VARCHAR(SIZE) 可变长度字符串,最大长度 65535
BLOB 二进制数据
TEXT 大文本,不支持全文索引,不支持默认值
时间日期 DATE / DATETIME / TIMESTAMP 日期类型 (yyyy-mm-dd) (yyyy-mm-dd hh:mm:ss)timestamp 时间戳
String 类型 ENUM 类型 ENUM 是一个字符串对象,其值来自表创建时在列规定中显示枚举的一列值
SET 类型 SET 是一个字符串对象,可以有零或多个值,其值来自表创建时规定的允许的一列值。指定包括多个 set 成员的 set 列值时各成员之间用逗号间隔开。这样 set 成员值本身不能包含逗号。

二、数值类型

MySQL中的数值类型有如下几种:

类型 占用字节 带符号范围 (最小值~最大值) 无符号范围 (最小值~最大值)
TINYINT 1 -128 ~ 127 0 ~ 255
SMALLINT 2 -32768 ~ 32767 0 ~ 65535
MEDIUMINT 3 -8388608 ~ 8388607 0 ~ 16777215
INT 4 -2147483648 ~ 2147483647 0 ~ 4294967295
BIGINT 8 -9223372036854775808 ~ 9223372036854775807 0 ~ 18446744073709551615

在mysql表中建立属性列时,是按照列名称在前,类型在后的规则排列的。当我们向mysql的特定类型中插入不合法的数据,例如超出数值范围、数值类型输入字母等,mysql会直接拦截我们,不让我们做插入操作,从而保证数据的安全性和可靠性。

反过来,如果我们已经有数据被成功地插入到mysql中了,那么说明该数据在插入时一定是合法地。所以,一般而言,mysql中的数据类型本身也是一种约束。而这种约束就是为了迫使用户在进行插入操作时尽可能进行正确的插入。

当我们定义的列类型为bit类型时,在插入数据时,数据是以16进制的形式进行存储的。

在定义列的数据类型时,我们会发现有些时候int后面会有一个括号,里面带着数字,例如int(10)。这个括号的作用是配合zerofill来使用的。如果加上该字段,则该列数据无法存储负数(即自动带上unsigned字段),而且会在左侧自动补0,直到满足int后括号后内容的位数。

同时,int后括号里面的数字也规定了插入数据时最大位数,如果超出这个范围讲不允许插入。

使用方式就是在建表时定义列属性时在后面带上zerofill字段:

效果如下图所示:

在定义数据类型float、double和decimal时,都是按照x(M,D)的形式来定义,M表示长度位数,而D表示小数位数。整数位数=M-D。

float、double和decimal的区别

|------------------------------|-----------------------------|
| FLOAT(M,D) UNSIGNED | M 指定显示长度,d 指定小数位数,占用 4 字节 |
| DOUBLE(M,D) UNSIGNED | 表示比 float 精度更大的小数,占用空间 8 字节 |
| DECIMAL(M,D) UNSIGNED | 定点数,M 指定长度,D 表示小数点的位数 |

float 类型能够保证的有效精度大约为 7 位,double 类型能够保证的有效精度大约为 16 位;而 decimal 类型有固定的位数限制,整数部分最大位数 m 为 65,小数部分最大位数 d 为 30。如果定义时省略 d 参数,小数位数默认值为 0;如果省略 m 参数,总位数默认值为 10。

在保存小数时,当超出小数的位数时,float、double和decimal都会进行四舍五入操作,但是四舍五入的逻辑不同。float和double是先将十进制数再转化为二进制浮点数,然后再和23.345进行判断,如果小于就舍去,如果大于就进一。而decimal则是按照原始的十进制来进行四舍五入。

(图中的num1、num2、num3分别是float、double、decimal类型)

所以当存储数值精度超出 float、double 的有效范围时,float 与 double 会自动对存入的数据做近似调整,直接产生精度丢失问题,decimal 则不存在该问题,存入的数值会完整精准保存。因此在业务中存储小数类数据 时,推荐使用 decimal 类型。

三、字符类型

|---------------|--------------------|
| CHAR(SIZE) | 固定长度字符串,最大 255 |
| VARCHAR(SIZE) | 可变长度字符串,最大长度 65535 |

在定义字符类型时可以像下面这样操作:

char 类型与 varchar 类型定义时后方括号内的数字,都代表字段能够存储的最大字符数量。但 char 和 varchar 存在核心区别:char 类型定义时存储空间长度固定,varchar 会根据实际存入数据动态分配存储空间,对比 char 拥有更高的磁盘空间利用率。

虽然在 utf8 编码下单个中文汉字会占用三个字节,但插入数据时 char、varchar 这类字符类型会将单个汉字识别为一个完整字符。由此可以确定,括号内设置的数值统计单位是字符个数,而非字节数量。

四、日期类型

|-----------------------------|------------------------------------------------------|
| DATE / DATETIME / TIMESTAMP | 日期类型 (yyyy-mm-dd) (yyyy-mm-dd hh:mm:ss)timestamp 时间戳 |

DATE 类型仅支持存储年 - 月 - 日格式的日期数据,DATETIME 类型可以完整存储年 - 月 - 日 时:分: 秒的完整日期时间,而 timestamp 类型专门用来保存转换后的时间戳数据。

五、ENUM、SET枚举集合类型

enum 为单选枚举类型,创建字段时需要预先定义好全部可选值,插入数据时只能填写列表里其中一个固定选项,不允许填入列表之外的内容。 enum 括号内定义的所有选项互相独立,同一条记录的该字段只能选取其中单个值,无法同时存储多个枚举选项。

set 为多选集合类型,同样在建表时提前配置全部可选值,和 enum 的核心区别是 set 支持同时存入多个预设选项,多个值之间使用逗号分隔填写。 如果插入的数据不在预先定义的集合列表内,这条非法内容会直接被丢弃,仅保留合法的集合选项。

两者都会限制字段写入范围,约束数据只能使用预设内容,减少脏数据产生。enum 适用于单一状态场景,set 适用于可多选标签、属性场景。

使用示例:

插入数据:

也可以直接输入数字用来指代对应的选项,比如单选枚举 enum 里设定 1 代表男、2 代表女,输入其余数字都会判定为非法数据。但需要注意,多选集合 set 类型的数字取值规则和 enum 完全不同,填入的数字会先转换成二进制,采用位图的方式标记选项,二进制位中 1 代表选中对应项,0 代表不选中对应项。如下图所示:

这里的数字2的二进制是00010,数字5的二进制是00101,二进制从左到右对应比特位由低到高,所以数字2对应选中篮球,数字5对应同时选中足球和羽毛球。本例中一共只定义了5个爱好选项,因此可以输入的合法数值范围为0到2^5-1。

相关推荐
猫猫不是喵喵.6 小时前
从0到1创建一个微服务项目
java·数据库·微服务·1024程序员节
lsc_blog7 小时前
听到优化风声,先准备能由自己掌控的事
数据库·分布式·中间件·职场和发展·重构
墨痕诉清风7 小时前
SSRF漏洞实战记录+OSS桶命令执行+MCP漏洞
linux·服务器·数据库
Ashe81310 小时前
MySQL 慢日志先别急着加索引:三个指标能拦掉大半误判
数据库
ClouGence10 小时前
最基础的异构数据库 DDL 同步,我们踩过哪些坑?
数据库·mysql·postgresql
羑悻的小杀马特11 小时前
Redis持久化三剑客:RDB二进制快照、AOF文本日志、混合模式如何守护你的数据安全?
数据库·redis·缓存·aof·持久化存储·rdb
小呆爱发呆12 小时前
第三章 MySQL 库表操作
数据库·mysql·adb
时间的拾荒人12 小时前
Redis 进阶实战:渐进式遍历、持久化机制与事务详解
数据库·redis·缓存
普通人613 小时前
MySQL_FIND_IN_SET函数详解
android·数据库·mysql