
🔥承渊政道: 个人主页
❄️个人专栏: 《C语言基础语法知识》 《数据结构与算法》 《C++知识内容》 《Linux系统知识》 《算法刷题指南》 《测评文章活动推广》 《大模型语言路线学习》 《MySQL数据库学习》
✨逆境不吐心中苦,顺境不忘来时路!✨ 🎬 博主简介:

在学习 MySQL 数据库的过程中,数据类型是一个非常基础但又十分重要的知识点.无论是创建数据表、设计字段结构,还是后续进行数据存储、查询优化和性能调优,合理选择数据类型都会直接影响数据库的存储效率、查询速度以及数据的准确性.很多初学者在刚接触 MySQL 时,可能会简单地把数字都用
INT,文本都用VARCHAR,时间都用DATETIME.虽然这样在一些简单场景下可以正常使用,但随着业务复杂度提升,如果数据类型选择不合理,就可能带来存储空间浪费、查询性能下降,甚至数据精度丢失等问题.本文将围绕 MySQL 中常见的数据类型展开学习,包括数值类型、字符串类型、日期时间类型等内容,帮助大家理解不同数据类型的特点、使用场景以及选择方式.通过本文的学习,你将能够更加清晰地掌握 MySQL 数据类型的基础知识,并在实际建表时做出更合理的字段设计.废话不多说,下面跟着小编的节奏🎵一起去疯狂的学习吧!

目录
1.数据类型
1.1数据类型分类

这表是在总结 MySQL 常见数据类型,按用途分成几类:数值、文本/二进制、时间日期、字符串枚举集合.
1.数值类型
用于存数字.
BIT(M)
位类型,M 表示位数,默认是1,范围通常是1到64.适合存二进制位,比如开关状态.
TINYINT UNSIGNED
很小的整数.
有符号范围:-128 ~ 127
无符号范围:0 ~ 255
常用于状态值、年龄、小范围编号.
BOOL
布尔类型,用来表示真/假.
在 MySQL 中通常等价于 TINYINT(1),0 表示 false,1 表示 true.
SMALLINT UNSIGNED
小整数.
有符号范围:-32768 ~ 32767
无符号范围:0 ~ 65535
INT UNSIGNED
普通整数,最常用.
有符号范围大约是:-2^31 ~ 2^31-1
无符号范围:0 ~ 2^32-1
适合存用户 ID、数量、编号等.
BIGINT UNSIGNED
大整数.
有符号范围:-2^63 ~ 2^63-1
无符号范围:0 ~ 2^64-1
适合存特别大的编号,比如订单号、雪花 ID.
FLOAT(M,D) UNSIGNED
单精度浮点数.
M 表示总长度,D 表示小数位数.占 4 字节.
适合对精度要求不高的小数.
DOUBLE(M,D) UNSIGNED
双精度浮点数.占 8 字节.
比 FLOAT 精度更高,但仍然可能有精度误差.
DECIMAL(M,D) UNSIGNED
定点小数.
M 是总位数,D 是小数位数.
适合金额、价格、财务数据,因为它比 FLOAT/DOUBLE 更精确.
2.文本、二进制类型
用于存字符串或二进制内容.
CHAR(size)
固定长度字符串,最大 255.
比如 CHAR(10),不够 10 位也会按固定长度存储.
适合长度固定的数据,比如性别、国家代码、固定编号.
VARCHAR(size)
可变长度字符串,最大 65535.
实际占用空间按内容长度变化.
最常用,适合用户名、邮箱、标题、地址等.
BLOB
二进制数据类型.
可以存图片、文件、音频等二进制内容,但实际开发中通常更推荐存文件路径或 URL.
TEXT
大文本类型.
支持全文索引,不支持默认值.
适合文章内容、评论、简介等长文本.
3.时间日期类型
用于存日期和时间.
DATE
日期类型,格式是:
sql
yyyy-mm-dd
例如:
sql
2026-05-26
DATETIME
日期 + 时间,格式是:
sql
yyyy-mm-dd hh:mm:ss
例如:
sql
2026-05-26 14:30:00
TIMESTAMP
时间戳类型,通常也显示为日期时间格式.
它和时区关系更密切,常用于记录创建时间、更新时间.
4.String 类型中的特殊类型
ENUM 类型
枚举类型,只能从预先定义好的值中选择一个.
例如:
sql
gender ENUM('男', '女', '未知')
这个字段只能存 '男'、'女' 或 '未知' 其中一个.
SET 类型
集合类型,也是在建表时预先定义可选值,但一个字段可以选择多个值.
例如:
sql
hobby SET('篮球', '足球', '音乐', '阅读')
可以存:
sql
'篮球,音乐'
也就是说,ENUM 是 多选一 ,SET 是 多选多.
1.2数值类型

这表是在说明 MySQL 整数类型的存储字节数和取值范围.
表头含义:
| 列名 | 含义 |
|---|---|
| 类型 | MySQL 整数数据类型 |
| 字节 | 该类型占用的存储空间 |
| 最小值 | 该类型能存的最小整数 |
| 最大值 | 该类型能存的最大整数 |
其中"带符号的/无符号的"表示:
带符号 signed :可以存负数、0、正数.
无符号 unsigned:只能存 0 和正数,但正数范围会变大.
1.TINYINT
占 1 个字节.
带符号范围:
sql
-128 ~ 127
无符号范围:
sql
0 ~ 255
适合存很小的数字,比如状态码、性别、开关值等.
2.SMALLINT
占 2 个字节.
带符号范围:
sql
-32768 ~ 32767
无符号范围:
sql
0 ~ 65535
适合存较小范围的整数,比如年龄、库存数量、小编号等.
3.MEDIUMINT
占 3 个字节.
带符号范围:
sql
-8388608 ~ 8388607
无符号范围:
sql
0 ~ 16777215
它介于 SMALLINT 和 INT 之间,实际开发中用得比 INT 少.
4.INT
占 4 个字节.
带符号范围:
sql
-2147483648 ~ 2147483647
无符号范围:
sql
0 ~ 4294967295
这是最常用的整数类型,比如用户 ID、商品 ID、数量统计等.
5.BIGINT
占 8 个字节.
带符号范围:
sql
-9223372036854775808 ~ 9223372036854775807
无符号范围:
sql
0 ~ 18446744073709551615
适合存非常大的整数,比如大规模系统中的订单号、流水号、雪花 ID 等.
1.2.1tinyint类型
我们建一张名字叫t1的表:
sql
create table t1(
num tinyint
);

我们向表中插入一些数据:
sql
insert into t1 values (-128);
insert into t1 values (127);
insert into t1 values (0);
insert into t1 values (-1);
insert into t1 values (1);

数值越界测试:
sql
insert into t1 values (-129);
insert into t1 values (128);
insert into t1 values (130);

越界插入非法数值,导致报错!
我们建一张名字叫t2的表:
sql
create table t2(
num tinyint unsigned
);

我们向表中插入一些数据:
sql
insert into t2 values(0);
insert into t2 values(255);
insert into t2 values(100);

数值越界测试:
sql
insert into t2 values(-1);
insert into t2 values(256);

越界插入非法数值,导致报错!
说明:
在MySQL中,整型可以指定是有符号的和无符号的,默认是有符号的.
可以通过UNSIGNED来说明某个字段是无符号的.
如果我们向 mysql 特定的类型中插入不合法的数据,MySQL 一般都是直接拦截我们,不让我们做对应的操作!反过来,如果我们已经有数据被成功插入到mysql中了,一定插入的时候是合法的!
上面介绍的是整型类型的,其他类型自己推导.
注意:尽量不使用unsigned,对于int类型可能存放不下的数据,int unsigned同样可能存放不下,与其如此,还不如设计时,将int类型提升为bigint类型.
1.2.2bit类型
基本语法:
bash
bit[(M)] : 位字段类型。M表示每个值的位数,范围从1到64。如果M被忽略,默认为1。
BIT 是 MySQL 中的位类型,用来存储二进制位数据.
例子
sql
CREATE TABLE test_bit (
b1 BIT,
b2 BIT(4),
b3 BIT(8)
);
含义是:
| 字段 | 含义 |
|---|---|
b1 BIT |
默认 BIT(1),只能存 1 位 |
b2 BIT(4) |
存 4 位二进制数 |
b3 BIT(8) |
存 8 位二进制数 |
创建名字t3的表,插入bit类型的字段:
sql
create table t3(
id int,
online bit(1)
);

向表中插入一些数据:
sql
insert into t3 (id,online) values(123,0);
insert into t3 (id,online) values(124,1);


发现很怪异的现象,online的插入的数据0和1没有出现!
bit使用的注意事项:bit字段在显示时,是按照ASCII码对应的值显示.
如果想要数据回显,可以进行以下这种操作!
sql
select id, hex(online) from t3;

如果我们有这样的值,只存放0或1,这时可以定义bit(1).这样可以节省空间.
当插入数据过大了,会导致越界啦!
sql
insert into t3 (id,online) values(123,3);
insert into t3 (id,online) values(123,5);
insert into t3 (id,online) values(123,2);

1.2.3小数类型
1.2.3.1float
语法:
bash
float[(m, d)] [unsigned] : M指定显示长度,d指定小数位数,占用空间4个字节
案例:
bash
小数:float(4,2)表示的范围是-99.99 ~ 99.99,MySQL在保存值时会进行四舍五入。
我们创建一张名为t4的表进行验证一下:

向表中插入一些数据:

这些插入的数据都是没有问题的,但是超过那个范围呢?就是告诉我们无法插入!

案例:
bash
如果定义的是float(4,2) unsigned 这时,因为把它指定为无符号的数,范围是 0 ~ 99.99
我们创建一张名为t5的表进行验证一下:

我们发现超出范围的数据是无法被插入的!

1.2.3.2decimal
语法:
bash
decimal(m, d) [unsigned] : 定点数m指定长度,d表示小数点的位数
decimal(5,2) 表示的范围是 -999.99 ~ 999.99
decimal(5,2) unsigned 表示的范围 0 ~ 999.99
decimal和float很像,但是有区别:
float和decimal表示的精度不一样
创建名叫t6的表进行验证一下:

我们向表中插入数据,看看数据显示情况:


如果我们希望某个数据表示高精度,选择decimal

说明:float表示的精度大约是7位.
decimal整数最大位数m为65.支持小数最大位数d是30.如果d被省略,默认为0.如果m被省略,默认是10.建议:如果希望小数的精度高,推荐使用decimal.
1.3字符串类型
1.3.1char
语法:
bash
char(L): 固定长度字符串,L是可以存储的长度,单位为字符,最大长度值可以为255
创建名叫t7的表验证一下:

我们向表中插入数据,看看数据显示情况:

说明:char(2)表示可以存放两个字符,可以是字母或汉字,但是不能超过2个,最多只能是255

1.3.2varchar
语法:
bash
varchar(L): 可变长度字符串,L表示字符长度,最大长度65535个字节
创建名叫t8的表验证一下:

我们向表中插入数据,看看数据显示情况:


说明:
关于varchar(len),len到底是多大,这个len值,和表的编码密切相关:
varchar长度可以指定为0到65535之间的值,但是有1 - 3 个字节用于记录数据大小,所以说有效字节数是65532.
当我们的表的编码是utf8时,varchar(n)的参数n最大值是65532/3=21844因为utf中,一个字符占用3个字节,如果编码是gbk,varchar(n)的参数n最大是65532/2=32766(因为gbk中,一个字符占用2字节).
那么问题来了,当我改成6636,报错的信息为什么说最大说16383?

因为 VARCHAR(N) 里的 N 是字符数,不是字节数.
我执行的是:
sql
alter table t8 modify name varchar(65536);
MySQL 需要判断这个字段最多可能占多少 字节 .如果你的表或字段字符集是 utf8mb4,每个字符最多占 4 个字节,所以:
text
65536 个字符 × 4 字节 = 262144 字节
这远超 VARCHAR 在 MySQL 中的行内最大限制.
报错里显示的:
text
max = 16383
是因为在 utf8mb4 下:
text
16383 × 4 = 65532 字节
再加上 VARCHAR 自身需要的长度字节,刚好接近 MySQL 单行最大约 65535 字节的限制.所以 MySQL 告诉你:在当前字符集下,这个字段最大只能是 varchar(16383) 左右.
可以验证字符集:
sql
show create table t8;
或者:
sql
show full columns from t8;
如果用的是 latin1 这种单字节字符集,理论最大值会接近:
sql
varchar(65532)
但如果是 utf8mb4,最大就是大约:
sql
varchar(16383)
如果你确实需要存很长文本,应该改用:
sql
TEXT
例如:
sql
alter table t8 modify name text;
总结:65535 是字节上限,不是字符上限;utf8mb4 每字符最多4字节,所以最大字符数约等于 65535 / 4 = 16383.
1.3.3char和varchar比较
| 实际存储 | char(4) | varchar(4) | char 占用字节 | varchar 占用字节 |
|---|---|---|---|---|
| abcd | abcd | abcd | 4*3=12 | 4*3+1=13 |
| A | A | A | 4*3=12 | 1*3+1=4 |
| Abcde | × | × | 数据超过长度 | 数据超过长度 |
如何选择定长或变长字符串?
如果数据确定长度都一样,就使用定长(char),比如:身份证,手机号,md5
如果数据长度有变化,就使用变长(varchar),比如:名字,地址,但是你要保证最长的能存的进去.
定长的磁盘空间比较浪费,但是效率高.
变长的磁盘空间比较节省,但是效率低.
定长的意义是,直接开辟好对应的空间
变长的意义是,在不超过自定义范围的情况下,用多少,开辟多少.
1.4日期和时间类型
常用的日期有如下三个:
date :日期 'yyyy-mm-dd' ,占用三字节
datetime:时间日期格式 'yyyy-mm-dd HH:ii:ss' 表示范围从 1000 到 9999 ,占用八字节
timestamp:时间戳,从1970年开始的 yyyy-mm-dd HH:ii:ss 格式和 datetime 完全一致,占用四字节
创建名为t9的表,并插入数据:

早期 MySQL 或关闭了 explicit_defaults_for_timestamp 时的行为:
sql
create table t9 (
t1 date,
t2 datetime,
t3 timestamp
);
在某些旧版本或旧配置下,第一个 timestamp 字段会被 MySQL 自动加上默认属性,相当于变成:
sql
t3 timestamp not null
default current_timestamp
on update current_timestamp
所以图片里:
插入时不写 t3:
sql
insert into birthday(t1,t2)
values('1997-7-1','2008-8-8 12:1:1');
t3 会自动变成当前时间.
更新其他字段时:
sql
update birthday set t1='2000-1-1';
t3 又会自动更新成当前时间。
但我的自己的表里,desc t9; 已经显示得很清楚:
text
Field | Type | Null | Default
t3 | timestamp | YES | NULL
说明你的 t3 实际定义是:
sql
t3 timestamp null default null
所以我插入数据时没有给 t3 赋值,它当然就是:
text
NULL
如果想实现图片里的效果,需要明确写出来:
sql
create table birthday (
t1 date,
t2 datetime,
t3 timestamp default current_timestamp on update current_timestamp
);
或者修改我已有的表:
sql
alter table t9
modify t3 timestamp default current_timestamp on update current_timestamp;
之后再插入时不写 t3,它就会自动填当前时间;更新其他字段时,t3 也会自动更新.

1.5enum和set
语法:
1.enum:枚举,"单选"类型;
enum('选项1','选项2','选项3',...);
该设定只是提供了若干个选项的值,最终一个单元格中,实际只存储了其中一个值;而且出于效率考虑,这些值实际存储的是"数字",因为这些选项的每个选项值依次对应如下数字:1,2,3,...最多65535个;当我们添加枚举值时,也可以添加对应的数字编号.
2.set:集合,"多选"类型;
set('选项值1','选项值2','选项值3', ...);
该设定只是提供了若干个选项的值,最终一个单元格中,设计可存储了其中任意多个值;而且出于效率考虑,这些值实际存储的是"数字",因为这些选项的每个选项值依次对应如下数字:1,2,4,8,16,32,...最多64个.
说明:不建议在添加枚举值,集合值的时候采用数字的方式,因为不利于阅读.



查询性别为男的信息:

集合查询使用find_ in_ set函数:

🚀真正的勇者不是流泪的人,而是含泪奔跑的人!
敬请期待下一篇文章内容
每日心灵鸡汤: 海压竹枝低复举,风吹山角晦还明!
今天看到一句很棒的诗:"海压竹枝低复举,风吹山角晦还明."它的意思是"乌云终将消散,黑暗终将过去,光明终会重现,人生在世没有事事如意,能屈能伸,黑暗过后自有万丈光芒在等你".谨以此句,送给我也送给你们.所有的经历都可以成为成长,希望大家都不要再因为任何人任何事而否定自己.总会有不如意的,生活从来都是泥沙俱下,鲜花与荆棘并存,我们带着疲惫满满来,慢一点也好,步子小也好,走在往前走就好.所以,做回自己,和朋友保持联系,按时睡觉不要再胡思乱想,爱情很好,没有也好,我们这样年纪本就该是骄傲的."海压竹枝低复举,风吹山角晦还明."我们终将上岸,阳光万里.
