跳到主要内容
MySQL 数据类型核心指南:选型、实战与避坑 | 极客日志
SQL java
MySQL 数据类型核心指南:选型、实战与避坑 MySQL 数据类型直接影响存储效率与查询性能。本文详解数值、字符串、日期及特殊类型的选型原则与实战测试,涵盖 INT、DECIMAL、CHAR、VARCHAR 等核心类型的使用场景、精度差异及常见陷阱,帮助开发者避免数据溢出、精度丢失等问题,实现数据库设计的优化。重点包括整数范围选择、浮点精度控制、定长与变长字符串的空间权衡,以及日期类型的时区与自动更新机制。通过实际 SQL 测试验证各类特性的表现,提供可直接落地的选型建议。
Pythonist 发布于 2026/3/16 0 浏览在 MySQL 数据库设计中,数据类型的选择直接影响存储效率、查询性能和数据准确性。选对类型能避免存储空间浪费、数据溢出和精度丢失,而选错则可能导致系统隐患(例如用 INT 存储手机号导致截断)。本文将全面拆解 MySQL 核心数据类型,结合实战案例讲解选型技巧。
MySQL 数据类型分类总览
MySQL 的数据类型丰富,按功能可分为五大类,覆盖数值、字符串、日期、特殊类型等场景:
分类 核心类型 适用场景 数值类型 BIT、TINYINT、INT、BIGINT、FLOAT、DECIMAL 存储数字(年龄、金额、计数等) 字符串类型 CHAR、VARCHAR、TEXT、BLOB 存储文本(姓名、地址、大文本、二进制数据) 日期时间类型 DATE、DATETIME、TIMESTAMP 存储时间(生日、创建时间、时间戳) 特殊字符串 ENUM(枚举)、SET(集合) 固定选项(性别、爱好、状态等) 二进制类型 BLOB 存储图片、文件等二进制数据
数值类型:精准匹配数字范围与精度
数值类型是最常用的类型,核心关注范围和精度,避免数据溢出或精度丢失。
2.1 整数类型(BIT/TINYINT/INT/BIGINT)
整数类型按占用字节和范围分为 5 类,支持 UNSIGNED(无符号)修饰(默认有符号):
类型 占用字节 有符号范围 无符号范围 适用场景 BIT(M) 1-8 1-64 位(默认 1 位) 同有符号 存储 0/1(性别)、位掩码 TINYINT 1 -128 ~ 127 0 ~ 255 年龄、状态值(0-255) SMALLINT 2 -32768 ~ 32767 0 ~ 65535 小范围计数(如订单编号) INT 4 -2147483648 ~ 2147483647 0 ~ 4294967295 普通计数(如用户 ID) BIGINT 8 -9e18 ~ 9e18 0 ~ 1.8e19 大数值(如手机号、雪花 ID)
关键实战要点 :
避免无符号类型(UNSIGNED) :虽然无符号类型能扩大正数范围,但可能导致溢出时报错(如 TINYINT UNSIGNED 插入 -1 直接报错),且与有符号类型计算时容易出现逻辑问题。建议直接用更大的整数类型(如用 INT 替代 TINYINT UNSIGNED)。
BIT 类型的坑 :BIT 字段存储的是位数据,查询时会按 ASCII 码显示(如 bit(8) 存储 10 显示为换行符,存储 65 显示为 'A'),仅适合存储 0/1 等简单标识。
CREATE TABLE tt5 (gender BIT( ));
tt5 ( );
tt5 ( );
tt5 ( );
1
INSERT INTO
VALUES
0
INSERT INTO
VALUES
1
INSERT INTO
VALUES
2
2.1.1 TINYINT 类型测试 TINYINT 占用 1 字节,有符号范围 -128127,无符号范围 0255:
CREATE TABLE test_tinyint1 (age TINYINT);
INSERT INTO test_tinyint1 VALUES (127 );
INSERT INTO test_tinyint1 VALUES (-128 );
INSERT INTO test_tinyint1 VALUES (128 );
CREATE TABLE test_tinyint2 (age TINYINT UNSIGNED);
INSERT INTO test_tinyint2 VALUES (255 );
INSERT INTO test_tinyint2 VALUES (-1 );
2.1.2 BIT 类型测试 BIT 存储位数据,默认 1 位(仅支持 0/1),位数 M 需≤64,查询时按 ASCII 码显示(易踩坑)。实际测试中有时也会显示为 16 进制,具体取决于客户端配置。
CREATE TABLE test_bit (gender BIT(1 ));
INSERT INTO test_bit VALUES (0 );
INSERT INTO test_bit VALUES (1 );
INSERT INTO test_bit VALUES (2 );
SELECT gender, bin(gender+ 0 ) FROM test_bit;
+--------+---------------+
| gender | bin(gender+0)|
+--------+---------------+
| | 0 |
| | 1 |
+--------+---------------+
注意:0 的 ASCII 显示为空白,转数字后是 0;1 同理。
2.1.3 INT/BIGINT 对比测试
CREATE TABLE test_int (phone INT );
INSERT INTO test_int VALUES (13800138000 );
CREATE TABLE test_bigint (phone BIGINT );
INSERT INTO test_bigint VALUES (13800138000 );
SELECT * FROM test_bigint;
2.2 小数类型(FLOAT/DOUBLE/DECIMAL) 小数类型用于存储带小数点的数值,核心区别在于精度 :
类型 占用字节 精度特性 适用场景 FLOAT 4 单精度,约 7 位有效数字 非精确计算(如身高、体重) DOUBLE 8 双精度,约 15 位有效数字 较高精度计算(如温度) DECIMAL 可变 高精度(自定义整数 + 小数位) 精确计算(如金额、税率)
2.2.1 FLOAT/DECIMAL 精度对比测试
CREATE TABLE test_decimal (
salary_float FLOAT (10 ,8 ),
salary_decimal DECIMAL (10 ,8 )
);
INSERT INTO test_decimal VALUES (23.12345612 , 23.12345612 );
SELECT * FROM test_decimal;
+---------------+----------------+
| salary_float | salary_decimal |
+---------------+----------------+
| 23.12345695 | 23.12345612 |
+---------------+----------------+
发现 DECIMAL 的精度更准确。因此如果我们希望某个数据表示高精度,选择 DECIMAL。
关键结论 :FLOAT 是近似存储,存在精度丢失;DECIMAL 是精确存储,适合金额、税率等场景。
FLOAT 表示的精度大约是 7 位,DECIMAL 整数最大位置 m 为 65,支持小数最大位置 d 是 30。如果 d 被省略,默认位 0,如果 m 被省略,默认是 10。建议如果希望小数的精度高,推荐使用 DECIMAL。
2.2.2 DECIMAL 范围测试 CREATE TABLE test_decimal2 (price DECIMAL (5 ,2 ));
INSERT INTO test_decimal2 VALUES (999.99 );
INSERT INTO test_decimal2 VALUES (1000.00 );
字符串类型:CHAR 与 VARCHAR 的终极选型 字符串类型是最容易用错的类型,核心是区分 CHAR(固定长度)和 VARCHAR(可变长度),以及 TEXT(大文本)的适用场景。
3.1 核心字符串类型对比 类型 长度限制 存储特性 适用场景 CHAR(L) L ≤ 255(字符) 固定长度,不足补空格 长度固定(身份证、手机号) VARCHAR(L) L ≤ 65535(字节) 可变长度,存储实际长度 + 1-3 字节长度标识 长度不固定(姓名、地址) TEXT 最大 65535 字节 大文本,不支持默认值 / 全文索引 长文本(文章内容、备注) BLOB 最大 65535 字节 二进制存储 图片、文件等二进制数据
3.2 CHAR 与 VARCHAR 深度测试
CREATE TABLE test_char_varchar (
c_char CHAR (4 ),
c_varchar VARCHAR (4 )
) CHARSET= utf8;
INSERT INTO test_char_varchar VALUES ('abcd' , 'abcd' );
INSERT INTO test_char_varchar VALUES ('A' , 'A' );
INSERT INTO test_char_varchar VALUES ('中国' , '中国' );
SELECT
c_char, LENGTH(c_char),
c_varchar, LENGTH(c_varchar)
FROM test_char_varchar;
+--------+---------------+------------+------------------+
| c_char | LENGTH (c_char)| c_varchar | LENGTH (c_varchar)|
+--------+---------------+------------+------------------+
| abcd | 12 | abcd | 13 |
| A | 12 | A | 4 |
| 中国 | 12 | 中国 | 7 |
+--------+---------------+------------+------------------+
CHAR(4) 无论存储多少字符,都占用 12 字节(4×3),不足补空格;
VARCHAR(4) 存储 1 字符占用 4 字节(3+1),2 字符占用 7 字节(6+1),4 字符占用 13 字节(12+1),更节省空间。
如何选择定长或变长字符串?
如果数据确定长度都一样,就使用定长(CHAR),比如:身份证、手机号、MD5。
如果数据长度有变化,就使用变长(VARCHAR),比如:名字、地址,但是你要保证最长的能存进去。
定长的磁盘空间比较浪费,但是效率高。
变长的磁盘空间比较节省,但是效率低。
定长的意义是,直接开辟好对应的空间。
变长的意义是,在不超过自定义范围的情况下,用多少,开辟多少。
3.3 VARCHAR 长度限制测试
CREATE TABLE test_varchar_limit1 (name VARCHAR (21845 )) CHARSET= utf8;
CREATE TABLE test_varchar_limit2 (name VARCHAR (21844 )) CHARSET= utf8;
日期时间类型:DATE/DATETIME/TIMESTAMP 选型 日期时间类型用于存储时间相关数据,核心是区分三者的存储范围、时区特性和自动更新机制:
类型 占用字节 时间范围 时区特性 自动更新 适用场景 DATE 3 1000-01-01 ~ 9999-12-31 无 无 生日、日期记录 DATETIME 8 1000-01-01 ~ 9999-12-31 无 无 固定时间(如订单创建时间) TIMESTAMP 4 1970-01-01 ~ 2038-01-19 受时区影响 支持自动更新 时间戳(如最后修改时间)
4.1 TIMESTAMP 自动更新测试
CREATE TABLE test_datetime (
t1 DATE ,
t2 DATETIME,
t3 TIMESTAMP
);
INSERT INTO test_datetime(t1,t2) VALUES ('1997-07-01' ,'2008-08-08 12:01:01' );
SELECT * FROM test_datetime;
+------------+---------------------+---------------------+
| t1 | t2 | t3 |
+------------+---------------------+---------------------+
| 1997-07-01 | 2008-08-08 12:01:01 | 2024-05-20 15:30:22 |
+------------+---------------------+---------------------+
-- t3 自动填充当前时间
UPDATE test_datetime SET t1= '2000-01-01' ;
SELECT * FROM test_datetime;
+------------+---------------------+---------------------+
| t1 | t2 | t3 |
+------------+---------------------+---------------------+
| 2000-01-01 | 2008-08-08 12:01:01 | 2024-05-20 15:35:48 |
+------------+---------------------+---------------------+
-- t3 自动更新为修改时间
特殊字符串类型:ENUM 与 SET(单选 / 多选场景) ENUM(枚举)和 SET(集合)适用于固定选项的场景,避免手动校验输入合法性。
5.1 ENUM(单选枚举)测试
CREATE TABLE test_enum (
username VARCHAR (30 ),
gender ENUM('男' ,'女' )
);
INSERT INTO test_enum VALUES ('雷锋' ,'男' );
INSERT INTO test_enum VALUES ('小红' ,2 );
INSERT INTO test_enum VALUES ('Tom' ,'未知' );
SELECT username, gender, gender+ 0 FROM test_enum;
+----------+--------+-----------+
| username | gender | gender+0 |
+----------+--------+-----------+
| 雷锋 | 男 | 1 |
| 小红 | 女 | 2 |
+----------+--------+-----------+
5.2 SET(多选集合)测试
CREATE TABLE test_set (
username VARCHAR (30 ),
hobby SET ('登山' ,'游泳' ,'篮球' ,'武术' )
);
INSERT INTO test_set VALUES ('雷锋' ,'登山,武术' );
INSERT INTO test_set VALUES ('小红' ,'游泳' );
INSERT INTO test_set VALUES ('Tom' ,'登山,游戏' );
SELECT * FROM test_set WHERE FIND_IN_SET('登山' , hobby);
+----------+-----------+
| username | hobby |
+----------+-----------+
| 雷锋 | 登山,武术 |
| Tom | 登山 |
+----------+-----------+
SET 的这个也可以用数字来代表,不过是由比特位来算的,比如 1 代表登山,2 代表游泳,3 代表的是登山和游泳 (0011)。
数据类型选型避坑指南和总结
按'最小必要'原则选型 :如年龄用 TINYINT(0-255 足够),不用 INT;金额用 DECIMAL(10,2),不用 FLOAT。
避免用字符串存储数字 :如手机号用 BIGINT 或 CHAR(11),不用 VARCHAR(11)(CHAR 查询更快);身份证用 CHAR(18)(固定长度),不用 VARCHAR。
BIT 类型查询需转数字 :直接查询 BIT 字段显示 ASCII 字符,需用 gender+0 或 CAST(gender AS UNSIGNED) 转为数字。
慎用 TEXT/BLOB :大文本类型会降低查询性能,若能拆分字段(如将文章摘要单独存储为 VARCHAR),尽量避免直接用 TEXT。
日期类型优先选 DATETIME :除非明确需要时区转换或自动更新,否则 DATETIME 的兼容性和范围更优,避免 TIMESTAMP 的 2038 限制。
总结 :MySQL 数据类型的选择核心是'匹配场景 + 平衡性能与空间',关键要点如下:
BIT/TINYINT 有严格范围限制,插入越界值会直接报错,查询 BIT 需转数字;
FLOAT 存在精度丢失,金额等精确场景必须用 DECIMAL;
CHAR 适合固定长度字符串(如手机号),VARCHAR 适合可变长度字符串(如姓名);
TIMESTAMP 支持自动更新,但有 2038 年限制,普通场景优先用 DATETIME;
ENUM/SET 简化固定选项存储,SET 查询需用 find_in_set 函数。
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
SQL 美化和格式化 在线格式化和美化您的 SQL 查询(它支持各种 SQL 方言)。 在线工具,SQL 美化和格式化在线工具,online
SQL转CSV/JSON/XML 解析 INSERT 等受限 SQL,导出为 CSV、JSON、XML、YAML、HTML 表格(见页内语法说明)。 在线工具,SQL转CSV/JSON/XML在线工具,online