上一篇学了简单的操作,现在我们再来认识一下MySQL数据类型.
目录
[(一) MySQL的数据类型](#(一) MySQL的数据类型)
[1. 数据类型分类](#1. 数据类型分类)
[2.1 tinyint类型](#2.1 tinyint类型)
[2.2 BIT 类型](#2.2 BIT 类型)
[3. 小数类型](#3. 小数类型)
[3.1 float 类型](#3.1 float 类型)
[3.2 decimal 类型(高精度定点数)](#3.2 decimal 类型(高精度定点数))
[核心区别:FLOAT 与 DECIMAL 精度对比](#核心区别:FLOAT 与 DECIMAL 精度对比)
[4. 字符串类型](#4. 字符串类型)
[4.1 char 固定长度字符串](#4.1 char 固定长度字符串)
[4.2 VARCHAR 可变长度字符串](#4.2 VARCHAR 可变长度字符串)
[4.3 CHAR 与 VARCHAR 对比与选择](#4.3 CHAR 与 VARCHAR 对比与选择)
[5. 日期和时间类型](#5. 日期和时间类型)
[6. enum 和 set 类型(字符串约束类型)](#6. enum 和 set 类型(字符串约束类型))
[1. ENUM 枚举(单选类型)](#1. ENUM 枚举(单选类型))
[2. SET 集合(多选类型)](#2. SET 集合(多选类型))
[3. find_in_set 函数说明](#3. find_in_set 函数说明)
(一) MySQL的数据类型
1. 数据类型分类
我们先来简单看看大概分类

大致解读:这张表是MySQL 数据类型的分类速查表 ,按存储类别划分,核心作用是快速查阅各类数据的定义规则、存储特性与适用场景,整体分为 4 大类别:
- 数值类型:涵盖整数(BIT、TINYINT、INT 等)、浮点数 / 定点数(FLOAT、DECIMAL 等),明确标注了各类型的位数、是否带符号、精度及存储规则,是定义数字字段(如 ID、数量、金额)的核心参考。
- 文本、二进制类型:包含字符串(CHAR、VARCHAR)、大文本 / 二进制数据(TEXT、BLOB),区分了固定长度与可变长度字符串,同时说明 TEXT/BLOB 的特殊限制(如不支持全文索引)。
- 时间日期类型:聚焦 DATE、DATETIME、TIMESTAMP,直接标注格式(yyyy-mm-dd、yyyy-mm-dd hh:mm:ss)与时间戳特性,明确时间类字段的存储形式。
- String 类型:为字符串扩展类型,ENUM(枚举,单选预设值)、SET(集合,多选预设值),用于限制字段的合法取值范围,规范数据录入。
2.数值类型

大致解读:这张表是MySQL 整数类型的精准参数表,聚焦整数类型的核心硬件与范围特性
2.1 tinyint类型
(1)默认有符号 TINYINT 测试
在 MySQL 中,整型默认是有符号的 ,TINYINT 有符号的取值范围为:-128 ~ 127。
先创建一个表:(注意一定要先进入库中,如 use mqlearn)
create table if not exists t1( num tinyint);
先插入一个合理的数据
insert into t1 values(1);
//运行结果:
Query OK, 1 row affected (0.00 sec)
可知合法的
试试插入一个超出范围的:如128
insert into t1 values(128);
//运行结果:
ERROR 1264 (22003): Out of range value for column 'num' at row 1
可知直接报错了
我们来看看表中数据:

(2)无符号 TINYINT(UNSIGNED)测试
通过 UNSIGNED 关键字可将字段设置为无符号类型 ,仅允许存储非负数,TINYINT UNSIGNED 取值范围为:0 ~ 255。
在创建一个表:
create table if not exists t2( num tinyint unsigned);
插入一个负数 -1
insert into t2 values(-1);
//运行结果:
ERROR 1264 (22003): Out of range value for column 'num' at row 1
可知超出范围报错
再试试插入最大值 255
insert into t2 values(255);
//运行结果:
Query OK, 1 row affected (0.00 sec)
可知插入成功
查看表中数据:

推导与规范说明
- 在MySQL中,整型可以指定是有符号的和无符号的,默认是有符号的。可以通过UNSIGNED来说明某个字段是无符号的
- 其他整型(SMALLINT/INT/BIGINT)的有符号 / 无符号规则与 TINYINT 完全一致,仅取值范围不同,可按此逻辑自行推导。
- 开发规范建议 :尽量不要使用 UNSIGNED 无符号类型。对于 INT 类型存不下的数据,INT UNSIGNED 通常也无法安全存储,直接将字段类型升级为 BIGINT 是更稳妥、更通用的设计方案。
2.2 BIT 类型
(1)基本语法
BIT[(M)]:位字段类型,用于存储二进制位数据
解释:
- M :表示每个值的位数 ,取值范围:1 ~ 64
- 省略 M 时,默认值为 1
(2)基础使用示例
先创建一个表
create table if not exists t3( id int, a bit(8) );
紧接着插入(10,10)
insert into t3 values(10,10);
运行结果:

解释:
BIT(M) 是二进制位类型,专门用来存储二进制数据,BIT(8) 就是 1 字节(8 个二进制位)的存储空间。
插入的 10 是十进制整数,MySQL 会把它自动转为二进制 1010,补全 8 位就是 00001010,再转为十六进制就是 0x0A。而有些伙伴会出现空白也是正常的------出现空白的情况,本质是客户端 / 版本差异 + 不可见字符的显示问题。
再看看输入(65,65)
BIT 字段在查询显示时,会自动按照 ASCII 码 对应字符展示,而非直接显示数字。
insert into t3 values (65,65);
再看一下表中

该现象也是正常,有些65右边可能得到A,现象解释:
插入 65,对应 ASCII 码就是字母 A。新版 MySQL 命令行默认把 bit 类型以 十六进制(0x41) 显示。
把 bit 类型以 ** 字符(A)** 显示。可以使用
CHAR(a)函数可以强制显示为字符
select id, cast(a as char) as a from t3;运行结果:
(3)BIT 类型最佳使用场景
当字段仅需存储 0 或 1 (如布尔状态、性别开关)时,使用 BIT(1) 可极大节省存储空间。
在创建一个表
create table if not exists t4( gender bit(1) );
插入结果:
//插入 0,成功
mysql> insert into t4 values(0);
Query OK, 1 row affected (0.01 sec)
//插入 1,成功
mysql> insert into t4 values(1);
Query OK, 1 row affected (0.01 sec)
//插入失败,2已经越界了
mysql> insert into t4 values(2);
ERROR 1406 (22001): Data too long for column 'gender' at row 1
总结
BIT(M)用于存储二进制位,M 范围 1~64,默认 1- 查询时按 ASCII 码显示字符,不会直接显示数字(按照不同版本来的)
- 最适合存储 0/1 二值状态,空间利用率最高
3. 小数类型
3.1 float 类型
语法
FLOAT[(M, D)] [UNSIGNED]
解释:
- M:总有效数字长度(整数位 + 小数位)
- D:小数点后的位数
- 占用 4 字节 存储空间
- 存储时会自动四舍五入
案例 1:有符号 FLOAT
FLOAT(4,2) 表示:总共 4 位数字,其中小数占 2 位取值范围 :-99.99 ~ 99.99
创建表
create table if not exists t6( id int, salary float(4,2) );
插入:
-- 插入合法最小值
mysql> insert into tt6 values(100, -99.99);
-- 插入超界小数,多出来会怎么样?
mysql> insert into tt6 values(101, -99.991);
-- 插入正常值89.992,多出来会怎么样?
mysql> insert into t6 values(102, 89.992);
Query OK, 1 row affected (0.00 sec)
-- 插入正常值89.999,多出来会怎么样?
mysql> insert into t6 values(103, 89.999);
Query OK, 1 row affected (0.00 sec)
查询结果

发现多出的部分------MySQL在保存值时会进行四舍五入。
故也可知范围推导 :FLOAT(6,3) 取值范围:-999.999 ~ 999.999
案例 2:无符号 FLOAT
FLOAT(4,2) UNSIGNED取值范围 :0 ~ 99.99(不允许负数)
创建表
create table if not exists t6( id int, salary float(4,2) unsigned);
插入
-- 插入负数,报越界警告
mysql> insert into tt7 values(100, -0.1);
ERROR 1146 (42S02): Table 'mqlearn.tt7' doesn't exist
查看警告
mysql> show warnings;

再插入几个合法值:
mysql> insert into t7 values(101,98.992);
ERROR 1146 (42S02): Table 'mqlearn.tt7' doesn't exist
mysql> insert into t7 values(101,98.992);
Query OK, 1 row affected (0.00 sec)
查看表格:

发现还是四舍五入的。
3.2 decimal 类型(高精度定点数)
语法
DECIMAL(M, D) [UNSIGNED]
解释:
- M:总有效位数(最大 65)
- D:小数位数(最大 30)
- 省略 D 时默认 0 ,省略 M 时默认 10
- 精度绝对准确,无精度丢失
取值示例
DECIMAL(5,2):-999.99 ~ 999.99DECIMAL(5,2) UNSIGNED:0 ~ 999.99
核心区别:FLOAT 与 DECIMAL 精度对比
FLOAT 精度有限(约 7 位有效数字),会出现精度丢失;DECIMAL 为高精度定点数,完全精准。
创建表:
create table if not exists t8( id int, salary float(10,8), salary2 decimal(10,8) );
-- 插入相同数据
mysql> insert into t8 values(100, 23.12345612, 23.12345612);
Query OK, 1 row affected (0.00 sec)
查询对比:

结论:FLOAT 出现精度误差,DECIMAL 完全保留原始数据。
总结
- FLOAT:精度有限,适合普通小数(如温度、身高)
- DECIMAL :精度绝对准确,适合金额、价格、财务数据
- 高精度场景必须使用 DECIMAL,禁止用 FLOAT/DOUBLE
4. 字符串类型
4.1 char 固定长度字符串
语法
CHAR(L)
解释:
- 固定长度字符串类型
- L 表示最多可存储的字符个数,字母、汉字均按 1 个字符计算
- 最大长度 255 个字符
使用示例
创建表,name 字段最多存放 2 个字符
create table if not exists t9( id int, name char(2) );
插入
-- 插入字母
mysql> insert into t9 values(100, 'ab');
Query OK, 1 row affected (0.01 sec)
-- 插入汉字
mysql> insert into t9 values(100, '你好');
Query OK, 1 row affected (0.00 sec)
查询结果:

结果可知,
CHAR (L) 的长度单位是字符,而非字节:无论英文字母、数字还是汉字,每个字符都按 1 个单位计算 ,因此 CHAR(2) 既能存 2 个字母,也能存 2 个汉字;该规则同样适用于 VARCHAR (L)。
长度限制
CHAR(L) 中 L 最大只能为 255,超过会直接报错:
mysql> create table tt10(id int, name char(256));
ERROR 1074 (42000): Column length too big for column 'name' (max = 255); use BLOB or TEXT instead
4.2 VARCHAR 可变长度字符串
语法
VARCHAR(L)
解释:
- 可变长度字符串类型
- L 表示最多可存储的字符个数
- 理论最大长度受限于 65535 字节 ,但需预留 1~3 字节存储数据长度,因此有效最大字节为 65532
使用示例
创建表,name 最多存放 6 个字符
create table if not exists t10( id int, name varchar(6) );
插入
-- 插入数据
mysql> insert into t10 values (100,'hello');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t10 values(101,'我爱你,中国');
Query OK, 1 row affected (0.00 sec)
mysql> isnert into t10 (102,'我爱你,中国!');
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 'isnert into t10 (102,'我爱你,中国!')' at line 1
查询结果:

可知,标点符号也算一个字符。
最大字符数与字符集的关系
VARCHAR 的最大可设长度 L 与字符集有关:
-
UTF8 编码:1 字符 ≈ 3 字节 → 最大 L ≈ 65532 / 3 = 21844
-
GBK 编码:1 字符 ≈ 2 字节 → 最大 L ≈ 65532 / 2 = 32766
-- 超过 21844 报错
mysql> create table if not exists t11(name varchar(21845)) charset=utf8;
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs-- 21844 可正常创建
mysql> create table if not exists t11(name varchar(21844)) charset=utf8;
Query OK, 0 rows affected, 1 warning (0.01 sec)
4.3 CHAR 与 VARCHAR 对比与选择
核心区别
- CHAR:固定长度,创建时直接开辟固定空间
- VARCHAR:可变长度,按实际数据占用空间
优缺点
- CHAR:空间较浪费,但访问效率高
- VARCHAR:空间更节省,但效率略低
如何选择
- 长度基本固定的字段:优先用 CHAR例:身份证号、手机号、MD5 串、性别编码等
- 长度波动较大的字段:优先用 VARCHAR例:用户名、昵称、地址、标题、备注等
5. 日期和时间类型
MySQL 提供了多种时间存储类型,常用的有 DATE、DATETIME、TIMESTAMP 三种。
基本介绍
-
DATE
- 格式:
yyyy-MM-dd(仅日期) - 占用:3 字节
- 范围:1000-01-01 ~ 9999-12-31
- 格式:
-
DATETIME
- 格式:
yyyy-MM-dd HH:mm:ss(日期 + 时间) - 占用:8 字节
- 范围:1000-01-01 00:00:00 ~ 9999-12-31 23:59:59
- 格式:
-
TIMESTAMP
- 格式:
yyyy-MM-dd HH:mm:ss(与 DATETIME 显示一致) - 占用:4 字节
- 特点:自动更新,插入 / 更新数据时会自动填充为当前系统时间
- 格式:
案例演示
创建表格
create table if not exists birthday(t1 date, t2 datetime, t3 timestamp);
需要注意:
在创建
birthday表时,t3字段使用TIMESTAMP类型并设置DEFAULT CURRENT_TIMESTAMP。在 MySQL 8.0 版本中,该设置仅表示插入数据时自动填充当前时间 ,执行UPDATE修改其他字段时,t3不会自动更新。而低版本 MySQL(如 5.x)中,
TIMESTAMP字段默认自带ON UPDATE CURRENT_TIMESTAMP属性,修改数据时会自动刷新时间。因此想要在 MySQL 8.0 中实现更新时自动修改t3,需要显式添加ON UPDATE CURRENT_TIMESTAMP。完整指令:
drop table birthday; create table birthday( t1 date, t2 datetime, t3 timestamp DEFAULT CURRENT_TIMESTAMP -- 这里加了自动填充 );
插入
-- 插入数据(只给 t1、t2 赋值,t3 自动生成当前时间)
mysql> insert into birthday(t1,t2) values('2007-1-25', '2006-11-22 12:25:28');
Query OK, 1 row affected (0.00 sec)
查询:

更新数据:
mysql> update birthday set t1='2007-1-26';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
查看结果;

从结果可知:**TIMESTAMP 类型在插入数据时会自动填充当前系统时间,更新该行任意字段时,又会自动刷新为最新时间,**这是它和 DATE、DATETIME 最明显的区别,后两者不会自动赋值或自动更新。
6. enum 和 set 类型(字符串约束类型)
这两个类型都可以提前定义可选值,限制字段只能输入预设内容。
1. ENUM 枚举(单选类型)
- 语法:
ENUM('选项1','选项2','选项3', ...) - 特点:只能选一个值
- 底层:用数字 1、2、3...... 对应存储,最多 65535 个选项
- 插入时可以用字符串 ,也可以用数字
2. SET 集合(多选类型)
- 语法:
SET('选项1','选项2','选项3', ...) - 特点:可以选 0 个、1 个或多个值
- 底层:用二进制位(1、2、4、8......)存储,最多 64 个选项
- 多个值之间用英文逗号分隔
案例演示
创建表
create table if not exists votes(
username varchar(30),
hobby set('登山','游泳','篮球','武术'),
gender enum('男','女')
);
插入测试数据
-- 只选登山
mysql> insert into votes values('LiLei', '登山', '男');
Query OK, 1 row affected (0.00 sec)
-- 登山+武术+游泳
mysql> insert into votes values('雷锋', '登山,武术,游泳', '男');
Query OK, 1 row affected (0.00 sec)
-- 全部爱好都选
mysql> insert into votes values('Juse', '登山,游泳,篮球,武术', '女');
Query OK, 1 row affected (0.00 sec)
-- 不选登山,用于对比
mysql> insert into votes values('HanMeiMei', '游泳,篮球', '女');
Query OK, 1 row affected (0.00 sec)
直接使用等值匹配(错误查询)
select * from votes where hobby='登山';
现象:

由现象可知 :只查出了只选了登山的用户,同时选了多个爱好(登山 + 武术 + 游泳、全部爱好)的用户都没有出现。
用 find_in_set 函数查询(正确查询)
select * from votes where find_in_set('登山', hobby);
现象:

由现象知道 :所有包含登山的记录都被查询出来,无论只选一个,还是多选、全选。
3. find_in_set 函数说明
语法:
find_in_set(sub, str_list)
解释
- 功能:在以逗号分隔的字符串
str_list中查找sub - 返回结果:存在则返回位置下标,不存在则返回 0
示例:
mysql> select find_in_set('a', 'a,b,c');
+---------------------------+
| find_in_set('a', 'a,b,c') |
+---------------------------+
| 1 |
+---------------------------+
1 row in set (0.00 sec)
mysql> select find_in_set('d', 'a,b,c');
+---------------------------+
| find_in_set('d', 'a,b,c') |
+---------------------------+
| 0 |
+---------------------------+
1 row in set (0.00 sec)
本文介绍了MySQL的数据类型,大家后续有补充或发现疏漏、错误,欢迎在评论区一起交流探讨~感谢各位的阅读!
