当前位置: 首页 > news >正文

技术干货-MYSQL数据类型详解

前言

在 MySQL 数据库设计中,数据类型的选择直接影响数据规范性、存储效率和查询性能。除了 int、varchar、datetime 等基础类型,ENUM(枚举)和 SET(集合)是两种容易被忽略但极具实用价值的特殊字符串类型 —— 它们通过预定义选项限制输入值,既能保证数据一致性,又能节省存储空间。

本文将从数据类型分类切入,先铺垫数值、字符串、日期等基础类型的核心逻辑,再聚焦 ENUM 和 SET 类型的语法定义、使用场景、实战案例,最后通过核心区别对比和注意事项总结,帮你彻底搞懂这两种类型的适用场景,避免在实际开发中踩坑。

目录

数据类型分类

数值类型

tinyint类型

bit类型

小数类型

decimal

字符串类型

char

varchar

日期和时间类型

enum和set

ENUM(枚举类型):单选场景

SET(集合类型):多选场景

综合案例测试

ENUM 与 SET 的核心区别

使用注意事项

总结

数据类型分类

下面是 MySQL 主要数据类型的分类表格,按常用场景分为数值型字符串型日期时间型特殊类型四大类,包含常用类型、说明及适用场景:

类型大类细分类型说明(长度 / 范围)适用场景示例
数值型TINYINT1 字节,范围:-128~127(有符号);0~255(无符号,UNSIGNED性别(0/1)、状态标识(有限选项)
SMALLINT2 字节,范围:-32768~32767(有符号);0~65535(无符号)小范围数量(如班级人数)
MEDIUMINT3 字节,范围:-8388608~8388607(有符号);0~16777215(无符号)中等范围数量(如商品库存)
INT/INTEGER4 字节,范围:-2147483648~2147483647(有符号);0~4294967295(无符号)整数 ID(用户 ID、订单号)
BIGINT8 字节,范围:-9e18~9e18(有符号);0~1.8e19(无符号)大整数(如雪花 ID、海量数据计数)
FLOAT(M,D)4 字节单精度浮点,M总位数,D小数位(精度有限,可能有误差)非精确小数(如温度、重量)
DOUBLE(M,D)8 字节双精度浮点,精度高于FLOAT(仍可能有误差)科学计算、高精度非精确小数
DECIMAL(M,D)高精度定点数,M总位数(最大 65),D小数位(最大 30),无精度损失金额、汇率(需精确计算的数值)
字符串型CHAR(N)固定长度字符串,N为长度(1~255),不足补空格,查询时自动截断短固定长度字符串(如手机号、邮编)
VARCHAR(N)可变长度字符串,N为最大长度(1~65535,受行总长度限制),仅占实际长度 + 1/2 字节长度不固定的文本(如姓名、地址)
TEXT长文本,最大 65535 字节(约 64KB)短文、描述信息
MEDIUMTEXT中等长文本,最大 16777215 字节(约 16MB)文章内容、日志
LONGTEXT超长文本,最大 4294967295 字节(约 4GB)大型文档、HTML 内容
ENUM('值1','值2',...)枚举类型,只能从指定值中选一个(最多 65535 个选项)固定选项(如性别:男 / 女 / 未知)
SET('值1','值2',...)集合类型,可多选指定值(最多 64 个选项)多选项(如兴趣:足球,篮球,阅读)
日期时间型DATE日期,格式YYYY-MM-DD,范围 1000-01-01~9999-12-31生日、订单日期
TIME时间,格式HH:MM:SS,范围 - 838:59:59~838:59:59时长、打卡时间点
DATETIME日期 + 时间,格式YYYY-MM-DD HH:MM:SS,范围 1000-01-01 00:00:00~9999-12-31 23:59:59事件发生时间(如注册时间)
TIMESTAMP时间戳,格式同DATETIME,范围 1970-01-01 00:00:01~2038-01-19 03:14:07,受时区影响记录更新时间(自动更新)
YEAR年份,格式YYYY,范围 1901~2155 或 0000出生年份、产品发布年份
特殊类型BIT(N)位字段,N为位数(1~64),存储二进制数据权限标识(每一位代表一个权限)
BLOB二进制大对象,存储图片、文件等二进制数据(TINYBLOB/BLOB/MEDIUMBLOB/LONGBLOB小型图片、二进制文件
JSON存储 JSON 格式数据,支持索引和 JSON 函数操作灵活结构数据(如配置、动态属性)

说明:

  1. 数值型的 UNSIGNED 修饰符可取消负数范围,扩大正数上限(如 TINYINT UNSIGNED 范围 0~255)。
  2. 字符串型中,CHAR 适合长度固定的场景(查询效率略高),VARCHAR 适合长度可变的场景(节省空间)。
  3. 日期时间型中,DATETIME 不受时区影响,TIMESTAMP 会随数据库时区自动转换,需根据业务选择。
  4. 实际使用时需根据数据长度、精度要求和业务场景选择最合适的类型,避免过度占用空间或精度不足。

数值类型

tinyint类型

数值越界测试:
mysql> create table tt1;
ERROR 4028 (HY000): A table must have at least one visible column.
mysql> create table tt1(num tinyint);
Query OK, 0 rows affected (0.04 sec)mysql> insert into ttl values(1);
ERROR 1146 (42S02): Table 'test1.ttl' doesn't exist
mysql> insert into tt1 values(1);
Query OK, 1 row affected (0.01 sec)mysql> insert into tt1 values(128);
ERROR 1264 (22003): Out of range value for column 'num' at row 1
mysql> insert into tt1 values(-128);
Query OK, 1 row affected (0.01 sec)mysql> insert into tt1 values(-129);
ERROR 1264 (22003): Out of range value for column 'num' at row 1
mysql> insert into tt1 values(127);
Query OK, 1 row affected (0.00 sec)mysql> select *from tt1;
+------+
| num  |
+------+
|    1 |
| -128 |
|  127 |
+------+
3 rows in set (0.00 sec)
说明:
在MySQL中,整型可以指定是有符号的和无符号的,默认是有符号的。
可以通过UNSIGNED来说明某个字段是无符号的
无符号案例
mysql> create table tt2(num tinyint unsigned);
mysql> insert into tt2 values(-1); -- 无符号,范围是: 0 - 255
ERROR 1264 (22003): Out of range value for column 'num' at row 1
mysql> insert into tt2 values(255);
Query OK, 1 row affected (0.02 sec)
mysql> select * from tt2;
+------+
| num |
+------+
| 255 |
+------+
1 row in set (0.00 sec)

bit类型

bit[(M)] : 位字段类型。M表示每个值的位数,范围从1到64。如果M被忽略,默认为1。

BIT 类型是 MySQL 中高效存储二进制位数据的类型,其显示形式(十六进制)和与 ASCII 码的关联是二进制特性的体现。实际使用中,需根据场景选择:存储二进制标识用 BIT,存储普通数字用 TINYINT/INT,存储字符用 CHAR,避免因显示形式导致误解。

mysql> insert into ttl value(1,1);
ERROR 1146 (42S02): Table 'test.ttl' doesn't exist
mysql> insert into tt1 value(1,1);
Query OK, 1 row affected (0.00 sec)mysql> select *from tt1;
+------+------------+
| id   | a          |
+------+------------+
|    1 | 0x01       |
+------+------------+
1 row in set (0.00 sec)mysql> insert into tt1 value(10,10);
Query OK, 1 row affected (0.00 sec)mysql> select *from tt1;
+------+------------+
| id   | a          |
+------+------------+
|    1 | 0x01       |
|   10 | 0x0A       |
+------+------------+
2 rows in set (0.00 sec)mysql> insert into tt1 value(65,65);
Query OK, 1 row affected (0.00 sec)mysql> select *from tt1;
+------+------------+
| id   | a          |
+------+------------+
|    1 | 0x01       |
|   10 | 0x0A       |
|   65 | 0x41       |
+------+------------+
3 rows in set (0.00 sec)mysql> SELECT id, a, ASCII(a) AS ascii_code FROM tt1;
+------+------------+------------+
| id   | a          | ascii_code |
+------+------------+------------+
|    1 | 0x01       |          1 |
|   10 | 0x0A       |         10 |
|   65 | 0x41       |         65 |
+------+------------+------------+
3 rows in set (0.00 sec)

小数类型

float[(m, d)] [unsigned] : M指定显示长度,d指定小数位数,占用空间4个字节
小数:float(4,2)表示的范围是-99.99 ~ 99.99MySQL在保存值时会进行四舍五入。

当我们的float(4,2)如果是一个有符号的,则表示范围是-99.99 ~ 99.99,如果float(6,3),显而易见是-999.999到999.999

如果定义的是float(4,2) unsigned 这时,因为把它指定为无符号的数,范围是 0 ~ 99.99
mysql> create table tt7(id int, salary float(4,2) unsigned);
Query OK, 0 rows affected, 2 warnings (0.02 sec)mysql> insert into tt7 values(100, -0.1);
ERROR 1264 (22003): Out of range value for column 'salary' at row 1
mysql> show warnings;
+-------+------+-------------------------------------------------+
| Level | Code | Message                                         |
+-------+------+-------------------------------------------------+
| Error | 1264 | Out of range value for column 'salary' at row 1 |
+-------+------+-------------------------------------------------+
1 row in set (0.00 sec)mysql> insert into tt7 values(100, -0);
Query OK, 1 row affected (0.00 sec)mysql> insert into tt7 values(100, 99.99);
Query OK, 1 row affected (0.00 sec)

decimal

decimal(m, d) [unsigned] : 定点数m指定长度,d表示小数点的位数
decimal(5,2) 表示的范围是 -999.99 ~ 999.99
decimal(5,2) unsigned 表示的范围 0 ~ 999.99
decimal和float很像,但是有区别: float和decimal表示的精度不一样
mysql> create table tt8 ( id int, salary float(10,8), salary2
decimal(10,8));
mysql> insert into tt8 values(100,23.12345612, 23.12345612);
Query OK, 1 row affected (0.00 sec)
mysql> select * from tt8;
+------+-------------+-------------+
| id | salary | salary2 |
+------+-------------+-------------+
| 100 | 23.12345695 | 23.12345612 | # 发现decimal的精度更准确,因此如果我们希望某
个数据表示高精度,选择decimal
+------+-------------+-------------+
说明:float表示的精度大约是7位。
decimal整数最大位数m为65。支持小数最大位数d是30。如果d被省略,默认为0.如果m被省略,
默认是10。
建议:如果希望小数的精度高,推荐使用decimal

字符串类型

char

char(L): 固定长度字符串,L是可以存储的长度,单位为字符,最大长度值可以为255
mysql> create table tt9(id int, name char(2));
Query OK, 0 rows affected (0.00 sec)
mysql> insert into tt9 values(100, 'ab');
Query OK, 1 row affected (0.00 sec)
mysql> insert into tt9 values(101, '中国');
Query OK, 1 row affected (0.00 sec)
mysql> select * from tt9;
+------+--------+
| id | name |
+------+--------+
| 100 | ab |
| 101 | 中国 |
+------+--------+
说明:
char(2) 表示可以存放两个字符,可以是字母或汉字,但是不能超过2个, 最多只能是255

varchar

varchar(L): 可变长度字符串,L表示字符长度,最大长度65535个字节

说明
关于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字节)。
mysql> create table tt11(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
mysql> create table tt11(name varchar(21844)) charset=utf8;
Query OK, 0 rows affected, 1 warning (0.02 sec)mysql>
charvarchar比较

如何选择定长或变长字符串?
如果数据确定长度都一样,就使用定长(char),比如:身份证,手机号,md5
如果数据长度有变化,就使用变长(varchar), 比如:名字,地址,但是你要保证最长的能存的进去。
定长的磁盘空间比较浪费,但是效率高。
变长的磁盘空间比较节省,但是效率低。
定长的意义是,直接开辟好对应的空间
变长的意义是,在不超过自定义范围的情况下,用多少,开辟多少。

日期和时间类型

常用的日期有如下三个:
date :日期 'yyyy-mm-dd' ,占用三字节
datetime 时间日期格式 'yyyy-mm-dd HH:ii:ss' 表示范围从 1000 到 9999 ,占用八字节
timestamp :时间戳,从1970年开始的 yyyy-mm-dd HH:ii:ss 格式和 datetime 完全一致,占用
四字节
mysql> create table bir(-> t1 date,-> t2 datetime,-> t3 timestamp-> );
Query OK, 0 rows affected (0.02 sec)
mysql> insert into bir (t1,t2)values('2025-10-27','2025-10-27 12:1:1');
Query OK, 1 row affected (0.01 sec)mysql> select *from bir;
+------------+---------------------+------+
| t1         | t2                  | t3   |
+------------+---------------------+------+
| 2025-10-27 | 2025-10-27 12:01:01 | NULL |
+------------+---------------------+------+
1 row in set (0.00 sec)mysql> -- 修改表结构,重新定义t3
mysql> ALTER TABLE bir-> MODIFY COLUMN t3 timestamp-> DEFAULT CURRENT_TIMESTAMP  -- 插入时自动填当前时间-> ON UPDATE CURRENT_TIMESTAMP;  -- 更新时自动更新为当前时间
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0mysql> select *from bir;
+------------+---------------------+------+
| t1         | t2                  | t3   |
+------------+---------------------+------+
| 2025-10-27 | 2025-10-27 12:01:01 | NULL |
+------------+---------------------+------+
1 row in set (0.00 sec)mysql> -- 插入新记录(不指定t3)
mysql> INSERT INTO bir (t1, t2) VALUES ('2025-10-28', '2025-10-28 13:00:00');
Query OK, 1 row affected (0.00 sec)mysql>
mysql> -- 更新已有记录
mysql> UPDATE bir SET t1 = '2025-10-29' WHERE t1 = '2025-10-27';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0mysql> select *from bir;
+------------+---------------------+---------------------+
| t1         | t2                  | t3                  |
+------------+---------------------+---------------------+
| 2025-10-29 | 2025-10-27 12:01:01 | 2025-10-27 23:27:41 |
| 2025-10-28 | 2025-10-28 13:00:00 | 2025-10-27 23:27:40 |
+------------+---------------------+---------------------+
2 rows in set (0.00 sec)

enumset

ENUM 和 SET 是 MySQL 中两种特殊的字符串类型,用于存储预定义的离散值,主要区别在于 “单选” 和 “多选”,以及存储方式和使用场景的不同。

ENUM(枚举类型):单选场景

ENUM 用于存储只能从预定义选项中选择一个值的字段(类似 “单选题”)。

CREATE TABLE 表名 (字段名 ENUM('选项1', '选项2', '选项3', ...) [约束]
);
  • 选项列表最多支持 65535 个值(实际使用中通常远少于此)。
  • 每个选项对应一个隐藏的数字编号(从 1 开始递增),存储时实际保存的是编号(而非字符串),节省空间。

 特点

  • 单选性:插入或更新时,只能选择一个预定义的选项,不能多选。
  • 默认值:若未指定 NOT NULL,默认值为 NULL;若指定 DEFAULT,可设置一个默认选项。
  • 存储优化:以数字编号存储(1 字节),比直接存字符串更高效。
-- 创建包含ENUM字段的表(性别:男/女/保密)
CREATE TABLE user (id INT PRIMARY KEY,gender ENUM('男', '女', '保密') NOT NULL DEFAULT '保密'
);-- 插入数据(只能选一个选项)
INSERT INTO user (id, gender) VALUES
(1, '男'),    -- 合法
(2, '女'),    -- 合法
(3, '保密');  -- 合法(使用默认值也可)-- 错误:插入未定义的选项
INSERT INTO user (id, gender) VALUES (4, '其他');  -- 报错(值不在ENUM列表中)

SET(集合类型):多选场景

SET 用于存储可以从预定义选项中选择多个值的字段(类似 “多选题”),多个值之间用逗号分隔。

CREATE TABLE 表名 (字段名 SET('选项1', '选项2', '选项3', ...) [约束]
);
  • 选项列表最多支持 64 个值(受存储方式限制)。
  • 存储时以二进制位的形式保存(每个选项对应一个位),多个选项的组合通过位运算实现,同样节省空间。

 特点

  • 多选性:插入或更新时,可以选择多个预定义选项(用逗号分隔)。
  • 默认值:若未指定 NOT NULL,默认值为 NULL;若指定 DEFAULT,可设置一个或多个默认选项(用逗号分隔)。
  • 查询灵活性:可通过 FIND_IN_SET() 函数查询包含特定选项的记录。

综合案例测试

mysql> create table use_hbby(-> name varchar(20),-> hobby set('登山','游泳','篮球','武术'),-> gender enum('男','女') not null);
Query OK, 0 rows affected (0.03 sec)

插入部分数据

mysql> insert into use_hbby values('雷锋', '登山,武术', '男');mysql> insert into use_hbby values('Juse','登山,武术',2);mysql> insert into use_hbby values('胡志', '武术', '男');mysql> insert into use_hbby values('程坤', '游泳', '男');mysql> insert into use_hbby values('小红','登山','女');

查询数据

mysql> select * from use_hbby where gender=2;
+------+-----------+--------+
| name | hobby     | gender |
+------+-----------+--------+
| Juse | 登山,武术 | 女     |
| 小红 | 登山      | 女     |
+------+-----------+--------+
想查找所有喜欢登山的人
select * from votes where hobby='登山';不能查询出所有,爱好为登山的人。
集合查询使用find_ in_ set函数:
find_in_set(sub,str_list) :如果 sub str_list 中,则返回下标;如果不在,返回0
str_list 用逗号分隔的字符串。
select * from votes where find_in_set('登山', hobby);

ENUM 与 SET 的核心区别

特性ENUMSET
选择方式单选(只能选一个选项)多选(可选择多个选项)
选项数量限制最多 65535 个最多 64 个
存储方式数字编号(1 字节)二进制位(1-8 字节)
典型场景性别、学历、状态等兴趣爱好、标签、权限等
插入格式单个值(如 '男'多个值用逗号分隔(如 '读书,音乐'

使用注意事项

  1. 选项值的引号:定义时选项必须用单引号或双引号包裹(如 ENUM('男','女'))。
  2. 大小写敏感性:默认不区分大小写(如 '男' 和 '男' 视为同一值),但存储时按定义的大小写保存。
  3. 避免滥用:若选项可能频繁变动,不建议使用 ENUM 或 SET(修改选项需 alter 表结构),可考虑用关联表替代。
  4. SET 的查询效率:虽然 FIND_IN_SET() 可以查询,但效率低于普通索引查询,大量数据场景需谨慎。

总结

  • ENUM 适合 “单选” 场景,节省空间且使用简单;
  • SET 适合 “多选” 场景,支持灵活的组合选择;
  • 两者均通过预定义选项限制输入,保证数据规范性,但需根据实际需求选择使用。
http://www.dtcms.com/a/572600.html

相关文章:

  • 备份工具:rsync、Tar、Borg、Veeam 备份与恢复方案
  • 深入 Pinia 工作原理:响应式核心、持久化机制与缓存策略
  • 【前端】动态插入并渲染大量数据的方法-时间分片:使用requestAnimationFrame+DocumentFragment
  • 耶鲁大学Hello Robot研究解读:人类反馈策略的多样性与有效性
  • Unity摄像机鼠标右键旋转功能
  • Spring AI Alibaba文生图实战:从零开始编写AI图片生成Demo
  • 文本编辑器做网站国外设计师
  • 网站多久电子信息工程就业方向
  • 大连网站seo顾问企业开发网站公司
  • 南京网站设计搭建公司网站怎么做rss
  • 外包做网站谷歌seo优化
  • 博物馆网站 建设方案外贸短视频营销
  • 网站如何在360做提交微信开发公司怎么样
  • 广州微网站建设信息设计图案大全
  • 苏州吴中区专业做网站郑州哪里可以做网站
  • cms网站开发毕设简述网站建设的方法
  • 怎样建立网站挣钱网站建设功能选择表
  • 郑州加盟做网站开源程序网站
  • 万维网网站注册网站线下推广怎么做
  • 郑州 网站建设:网站开发页面大小适应屏幕
  • 网络营销网站建设知识南通关键词优化软件
  • 公司网站页脚dedecms手机网站模板
  • 团购网站建设公司深圳营销型网页设计公司
  • 东莞网站建设在哪里wordpress 加载中动画
  • 慈溪市建设局网站h5免费制作平台火蚁
  • 平凉北京网站建设百度店铺免费入驻
  • wordpress termmeta怎么把网站排名优化
  • 服装企业网站内容规划企业网站建设方案教程
  • 网站建设步骤和流程ico wordpress
  • 现在有什么网站可以做兼职的微信小程序开发大赛