MySQL 最全数据类型详解(数值/字符串/日期/枚举集合)

本文基于 MySQL 主流版本整理,涵盖所有常用数据类型、使用场景、底层原理、代码实战、易错点、选型建议。

一、前言

数据类型是建表的核心,选错类型会造成:存储空间浪费、查询效率低下、数据越界、精度丢失 等问题。MySQL 数据类型主要分为五大类:数值类型、位类型、字符串类型、日期时间类型、枚举&集合类型。下面从分类、语法、实战、易错点逐一讲解。


二、数值类型

数值类型分为整型、浮点型、定点数 ,支持 UNSIGNED(无符号)修饰符,默认有符号

2.1 整型(TINYINT / SMALLINT / MEDIUMINT / INT / BIGINT)

2.1.1 整型范围与字节对照表
数据类型 占用字节 有符号范围 无符号(UNSIGNED)范围
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
2.1.2 核心语法 & 代码实战

语法格式:

sql 复制代码
字段名  整型类型 [UNSIGNED]
示例1:默认有符号 TINYINT(数据越界演示)
sql 复制代码
-- 创建表,num 为默认有符号 TINYINT
CREATE TABLE test_tinyint(
    num TINYINT
);

-- 正常插入
INSERT INTO test_tinyint VALUES(100);

-- 越界插入(超过最大值127),直接报错
INSERT INTO test_tinyint VALUES(128);

报错说明ERROR 1264 (22003): Out of range value,表示数值超出当前类型定义范围。

示例2:无符号 UNSIGNED 整型

无符号整型不支持负数,最小值从 0 开始:

sql 复制代码
CREATE TABLE test_tinyint_unsigned(
    num TINYINT UNSIGNED
);

-- 插入负数,越界报错
INSERT INTO test_tinyint_unsigned VALUES(-1);

-- 插入最大值 255,正常执行
INSERT INTO test_tinyint_unsigned VALUES(255);
2.1.3 易错点 & 选型建议
  1. 不推荐滥用 UNSIGNED
    INT 存不下数据,INT UNSIGNED 大概率也存不下,直接升级为 BIGINT 是最优方案。
  2. 场景选型
    • 状态、性别、少量编号:用 TINYINT
    • 普通自增主键、常规数字:用 INT
    • 超大自增ID、长数字:用 BIGINT

2.2 BIT 位类型

2.2.1 语法规则
sql 复制代码
BIT[(M)]
  • M:位数,取值 1 ~ 64 ,省略 M 则默认 BIT(1)
  • 底层按二进制位存储,极度节省空间
  • 显示规则 :MySQL 会按照 ASCII 码 解析二进制值,不会直接显示数字
2.2.2 代码实战
sql 复制代码
-- 创建表:id 普通整型,a 占8位 BIT
CREATE TABLE test_bit(
    id INT,
    a BIT(8)
);

-- 插入数字 65(ASCII 65 = 大写字母 A)
INSERT INTO test_bit VALUES(1, 65);

-- 查询结果:a 列显示 A,而非 65
SELECT * FROM test_bit;
2.2.3 经典场景:布尔状态(0/1)

仅存储是/否、启用/禁用 等二值状态,优先使用 BIT(1),空间最优:

sql 复制代码
CREATE TABLE test_status(
    is_enable BIT(1)  -- 0=禁用,1=启用
);

INSERT INTO test_status VALUES(0);
INSERT INTO test_status VALUES(1);

-- 插入 2,超出 1 位范围,报错
INSERT INTO test_status VALUES(2);

报错Data too long for column,位数溢出。

2.3 浮点型 FLOAT

2.3.1 语法规则
sql 复制代码
FLOAT[(M,D)] [UNSIGNED]
  • 占用 4 字节
  • M:数据总显示长度(整数位+小数位)
  • D:小数位数
  • 特性:自动四舍五入,精度约7位有效数字,存在精度丢失
2.3.2 范围计算 & 实战
  1. FLOAT(4,2):总长度4,小数2位 → 范围 -99.99 ~ 99.99
  2. FLOAT(6,3):总长度6,小数3位 → 范围 -999.999 ~ 999.999

代码示例:

sql 复制代码
CREATE TABLE test_float(
    id INT,
    salary FLOAT(4,2)
);

-- 正常数据
INSERT INTO test_float VALUES(1, 99.99);

-- 小数位超出,自动四舍五入
INSERT INTO test_float VALUES(2, 99.991);

SELECT * FROM test_float;

查询结果:99.991 自动变为 99.99

2.3.3 无符号 FLOAT

无符号浮点不允许负数,负数会触发警告并修正:

sql 复制代码
CREATE TABLE test_float_unsigned(
    salary FLOAT(4,2) UNSIGNED
);

-- 插入负数,触发范围警告
INSERT INTO test_float_unsigned VALUES(-0.1);

2.4 定点数 DECIMAL(高精度小数)

2.4.1 语法规则
sql 复制代码
DECIMAL[(M,D)] [UNSIGNED]
  • 定点数,无精度丢失,金融、金额、账务场景首选
  • M:总位数(最大65),D:小数位数(最大30)
  • 省略 M 默认10,省略 D 默认0
2.4.2 FLOAT 与 DECIMAL 精度对比(重点)
sql 复制代码
CREATE TABLE test_decimal(
    id INT,
    num_float FLOAT(10,8),
    num_decimal DECIMAL(10,8)
);

-- 插入同一串高精度小数
INSERT INTO test_decimal VALUES(1, 23.12345612, 23.12345612);

SELECT * FROM test_decimal;

执行结果

  • FLOAT23.12345695(精度错乱、丢失)
  • DECIMAL23.12345612(完全精准)
2.4.3 选型总结
  • 普通小数、非精密计算:使用 FLOAT
  • 金额、货币、财务、科学计算 :强制使用 DECIMAL

三、字符串类型

字符串分为定长字符串 CHAR、可变长字符串 VARCHAR、大文本 TEXT、二进制 BLOB,是业务中使用频率最高的类型。

3.1 CHAR 定长字符串

3.1.1 语法 & 特性
sql 复制代码
CHAR(L)
  • L:字符长度,最大 255 字符
  • 固定占用空间:无论实际存多少字符,都会占满定义长度
  • 优点:查询、读写效率极高;缺点:浪费存储空间
3.1.2 代码实战
sql 复制代码
-- 固定存储 2 个字符
CREATE TABLE test_char(
    name CHAR(2)
);

-- 英文、中文都算作 1 个字符
INSERT INTO test_char VALUES('ab');
INSERT INTO test_char VALUES('中国');

-- 定义 CHAR(256) 直接报错,超出最大限制
CREATE TABLE test_char_err(name CHAR(256));
3.1.3 适用场景

数据长度固定的字段优先用 CHAR:

  • 手机号、身份证号、银行卡号
  • MD5 加密字符串、固定验证码

3.2 VARCHAR 可变长字符串

3.2.1 语法 & 底层规则
sql 复制代码
VARCHAR(L)
  • 可变长度:用多少空间占多少,节省存储
  • 底层会额外占用 1~3字节 记录字符串长度,最大有效字节 65532
  • 长度受字符集 限制(核心易错点):
    1. utf8 编码:1字符 = 3字节 → 最大字符数 65532 / 3 = 21844
    2. gbk 编码:1字符 = 2字节 → 最大字符数 65532 / 2 = 32766
3.2.2 代码实战(字符集限制演示)
sql 复制代码
-- utf8 编码,超过21844 直接报错
CREATE TABLE test_varchar_err(
    name VARCHAR(21845)
) CHARSET=utf8;

-- 合法定义
CREATE TABLE test_varchar(
    name VARCHAR(21844)
) CHARSET=utf8;

-- 中英文混合插入
INSERT INTO test_varchar VALUES('Hello MySQL');
INSERT INTO test_varchar VALUES('我爱编程,热爱技术');
3.2.3 CHAR 和 VARCHAR 对比表
类型 存储特点 空间利用率 查询效率 适用场景
CHAR 定长,不足补空格 固定长度数据
VARCHAR 变长,按需分配 略低 长度不固定数据
3.2.4 适用场景

数据长度不固定:用户名、昵称、地址、简介、备注等。

3.3 TEXT & BLOB 大文本/二进制

  1. TEXT :纯大文本,用于超长内容(文章正文、详情、大段备注)
    • 不支持默认值、部分索引规则和普通字符串不同
  2. BLOB :二进制数据,用于存储图片、文件、音频 等二进制流 开发规范:不建议数据库直接存图片/文件,优先存文件路径。

四、日期时间类型

MySQL 常用三大时间类型:DATEDATETIMETIMESTAMP,业务时间字段必学。

4.1 类型对比

类型 格式 占用字节 时间范围 特性
DATE yyyy-MM-dd(仅日期) 3 1000-01-01 ~ 9999-12-31 只存年月日
DATETIME yyyy-MM-dd HH:mm:ss(日期+时间) 8 1000-01-01 ~ 9999-12-31 23:59:59 全时间,不受时区严格限制
TIMESTAMP yyyy-MM-dd HH:mm:ss(时间戳) 4 1970-01-01 ~ 2038-01-19 自动更新、受时区影响

4.2 代码实战(核心特性:TIMESTAMP 自动刷新)

sql 复制代码
CREATE TABLE test_time(
    t_date DATE,
    t_datetime DATETIME,
    t_timestamp TIMESTAMP
);

-- 插入数据,timestamp 自动填充当前系统时间
INSERT INTO test_time(t_date, t_datetime) 
VALUES('2026-06-12', '2026-06-12 10:20:30');

-- 更新任意字段,timestamp 会自动刷新为最新时间
UPDATE test_time SET t_date = '2026-01-01';

SELECT * FROM test_time;

4.3 选型建议 & 易错点

  1. 2038 时间坑TIMESTAMP 最大到 2038 年,长期项目优先用 DATETIME
  2. 只需要年月日:用 DATE
  3. 需要精确到时分秒、长期使用:用 DATETIME
  4. 需记录数据最后修改时间 :可用 TIMESTAMP 自动更新特性

五、枚举 ENUM & 集合 SET

专门用于固定选项的字段,ENUM 单选、SET 多选,底层以数字存储,效率高。

5.1 ENUM 枚举(单选)

5.1.1 语法
sql 复制代码
ENUM('选项1','选项2','选项3'...)
  • 单选类型,一个字段只能选其中一个值
  • 底层存储数字编号:选项依次对应 1、2、3...
  • 最大支持 65535 个选项
5.1.2 实战:性别单选
sql 复制代码
CREATE TABLE test_enum(
    username VARCHAR(20),
    gender ENUM('男','女','未知')
);

-- 直接写入字符串(推荐,可读性强)
INSERT INTO test_enum VALUES('张三','男');

-- 也可以写数字编号(不推荐),1=男,2=女
INSERT INTO test_enum VALUES('李四',2);

-- 按数字查询
SELECT * FROM test_enum WHERE gender = 2;

5.2 SET 集合(多选)

5.2.1 语法
sql 复制代码
SET('选项1','选项2','选项3'...)
  • 多选类型,一个字段可同时选中多个选项,逗号分隔
  • 底层按二进制位 存储:选项依次对应 1、2、4、8、16...
  • 最大支持 64 个选项
5.2.2 实战:爱好多选
sql 复制代码
CREATE TABLE test_set(
    username VARCHAR(20),
    hobby SET('篮球','足球','游泳','跑步')
);

-- 插入多个爱好,逗号分隔
INSERT INTO test_set VALUES('王五','篮球,游泳');
INSERT INTO test_set VALUES('赵六','足球,跑步,篮球');

5.3 SET 专属查询函数 FIND_IN_SET(高频考点)

普通 WHERE 字段='值' 无法查询包含该选项的多条数据 ,必须使用 FIND_IN_SET(查询值, 字段)

错误写法
sql 复制代码
-- 只能精准匹配"只有篮球"的数据,查不到同时选篮球+游泳的人
SELECT * FROM test_set WHERE hobby = '篮球';
正确写法(通用查询)
sql 复制代码
-- 查询所有爱好包含"篮球"的用户(包含多选数据)
SELECT * FROM test_set WHERE FIND_IN_SET('篮球', hobby);

5.4 选型建议

  1. 固定单选(性别、学历、状态):用 ENUM
  2. 固定多选(爱好、标签、权限):用 SET
  3. 选项后期会频繁新增:不要用枚举/集合,改用字典表关联。

六、综合总结 & 开发规范

6.1 类型速选清单

  1. 整数
    • 状态/少量数字:TINYINT
    • 普通ID/编号:INT
    • 超大ID/长整型:BIGINT
    • 二值状态(0/1):BIT(1)
  2. 小数
    • 普通小数:FLOAT
    • 金额/财务/高精度:DECIMAL
  3. 字符串
    • 定长(手机号、身份证):CHAR
    • 变长(姓名、地址):VARCHAR
    • 超长文本(文章):TEXT
  4. 时间
    • 仅日期:DATE
    • 完整时间、长期项目:DATETIME
    • 自动更新修改时间(短期):TIMESTAMP
  5. 固定选项
    • 单选:ENUM
    • 多选标签:SET

6.2 高频易错点汇总

  1. 整型 UNSIGNED 不能存负数,非必要不使用
  2. VARCHAR 最大长度受字符集限制,utf8 最大字符数 21844
  3. BIT 类型按 ASCII 码显示,不直接展示数字
  4. FLOAT 存在精度丢失,金额严禁使用
  5. TIMESTAMP 存在 2038 年限,新项目优先 DATETIME
  6. SET 多选查询必须使用 FIND_IN_SET 函数

七、完整建表示例(综合运用)

sql 复制代码
-- 综合所有数据类型建表演示
CREATE TABLE user_info(
    id BIGINT PRIMARY KEY AUTO_INCREMENT,  -- 大整数主键
    phone CHAR(11),                       -- 定长手机号
    username VARCHAR(30),                 -- 变长用户名
    age TINYINT UNSIGNED,                 -- 年龄(无符号)
    balance DECIMAL(10,2),                -- 账户金额(高精度)
    gender ENUM('男','女','保密'),        -- 性别枚举
    hobby SET('阅读','运动','游戏'),       -- 爱好集合
    register_date DATE,                   -- 注册日期
    create_time DATETIME,                 -- 创建时间
    is_valid BIT(1)                       -- 启用状态 0/1
);

通过本文的详细讲解和代码示例,相信你对MySQL数据类型已经有了全面而深入的理解。在实际建表时,请根据业务需求、存储效率和查询性能综合权衡,选择最合适的数据类型。如果觉得有用,欢迎点赞收藏,支持作者继续输出更多数据库干货!

相关推荐
IT策士1 小时前
Redis 从入门到精通:Redis Sentinel 哨兵
数据库·redis·sentinel
云器科技1 小时前
螳螂科技:从组装到统一,如何用云器 Lakehouse 完美替代“MC+DW+ADB”三件套?
数据库·数据仓库·人工智能
Amnesia0_02 小时前
MySQL的访问和数据流动
数据库·mysql
AI2中文网2 小时前
App Inventor 2 数据库方案全览:从本地存储到云端服务
数据库·oracle·app inventor
Arbori_262152 小时前
找回mysql root 密码
数据库·mysql
zlpzlpzyd2 小时前
spring boot 4.1发布
java·数据库·spring boot
石一峰6992 小时前
SQLite 与 db_manager 集成关键概念详解
jvm·数据库·sqlite
pigs20182 小时前
mysql8.0 access denied for user root localhost account is locked
数据库·adb
阿里云瑶池数据库2 小时前
从开源插件到生产级引擎:PolarDB PostgreSQL的向量能力新范式
数据库·阿里云·postgresql