目录
本文内容概要
一、常见数据类型分类
二、数值类型
2.1 BIT 类型
2.2 整数类型 ---- TINYINT 类型
2.3 小数类型
2.3.1 浮点数 ---- FLOAT 类型
2.3.2 定点数 ---- DECIMAL 类型
2.4 文本/二进制类型
2.4.1 CHAR 类型
2.4.2 VARCHAR 类型
2.4.3 CHAR 和 VARCHAR 的区别
2.5 日期时间类型
2.5.1 DATE 类型
2.5.2 DATETIME 类型
2.5.3 TIMESTAMP 类型
2.6 String 类型
2.6.1 ENUM 类型
2.6.2 SET 类型
2.6.3 ENUM 和 SET 的区别
2.6.4 底层存储特点
本文内容概要
本文主要介绍MySQL 中常见的数据类型及其基本使用方法,从数据类型的分类入手,依次讲解数值类型、文本/二进制类型、日期时间类型以及 String 类型。
通过本文,你将了解:
- 数值类型:认识 BIT 位类型以及常见整数类型,理解有符号与无符号整数的取值范围;掌握 FLOAT 浮点数与 DECIMAL 定点数的特点及区别。
- 文本/二进制类型:重点学习 CHAR 和 VARCHAR 的使用方式,理解定长字符串与变长字符串在存储方式和应用场景上的区别。
- 日期时间类型:掌握 DATE、DATETIME、TIMESTAMP 的基本使用,理解三者的区别,以及 TIMESPTAMP 自动初始化和自动更新时间等特点。
- String 类型:理解 ENUM 类型与 SET 类型的使用方式、应用场景及二者区别,并简单了解其底层存储特点。
本文以常见类型为重点,结合SQL 示例、取值范围、实际存储特点和应用场景进行讲解,帮助读者建立对 MySQL 数据类型的整体认识,为后续学习表的约束、数据增删改查以及索引等内容打下基础。
一、常见数据类型分类
| 分类 | 数据类型 | 说明 |
|---|---|---|
| 数值类型 | BIT(M) | 位类型。M 指定位数,默认值为 1,范围 1~64 |
| 数值类型 | TINYINT[UNSIGNED] | 1 字节整数。有符号范围 -128~127,无符号范围 0~255 |
| 数值类型 | SMALLINT [UNSIGNED] | 2 字节整数。有符号范围 -32768~32767,无符号范围 0~65535 |
| 数值类型 | MEDIUMINT [UNSIGNED] | 3 字节整数。有符号范围 -8388608~8388607,无符号范围 0~16777215 |
| 数值类型 | INT[UNSIGNED] | 4 字节整数。有符号范围 -2³¹~2³¹-1,无符号范围 0~2³²-1 |
| 数值类型 | BIGINT [UNSIGNED] | 8 字节整数。有符号范围 -2⁶³~2⁶³-1,无符号范围 0~2⁶⁴-1 |
| 数值类型 | FLOAT(M,D) | 单精度浮点数,占用 4 字节,属于近似数值类型。M 表示数据位数,D表示小数位数 |
| 数值类型 | DOUBLE(M,D) | 双精度浮点数,占用 8 字节,精度高于 FLOATM。表示数据位数,D表示小数位数 |
| 数值类型 | DECIMAL(M,D) | 定点数,适合保存要求精确的小数。M 表示数据位数,D表示小数位数 |
| 文本 / 二进制类型 | CHAR(M) | 定长字符串,其中 M 表示字符串能够存储的最大字符数 |
| 文本 / 二进制类型 | VARCHAR(M) | 变长字符串,最大实际长度受字符集和单行 65535 字节限制 |
| 文本 / 二进制类型 | BLOB | 二进制大对象,最大约 64 KB |
| 文本 / 二进制类型 | TEXT | 文本数据,最大约 64 KB |
| 日期时间类型 | DATE | 日期,格式YYYY-MM-DD |
| 日期时间类型 | DATETIME | 日期和时间,格式YYYY-MM-DD HH:MM:SS |
| 日期时间类型 | TIMESTAMP | 时间戳类型,存储时涉及会话时区转换 |
| String 类型 | ENUM | 枚举类型,只能从预先定义的字符串列表中选择一个值 |
| String 类型 | SET | 集合类型,可以从预先定义的字符串列表中选择零个或多个值 |
二、数值类型
2.1 BIT 类型
bit(M) :比特位字段类型。M 表示比特位的数量,M 的取值范围位 1 ~ 64,其类型的数值取值范围为 0 ~ 2^M - 1。如果 M 被忽略,则默认比特位数量为 1,其数值取值范围为 0 ~ 1。
mysql> create table test(id bit(2), gender bit); Query OK, 0 rows affected (0.01 sec) mysql> desc test\G *************************** 1. row *************************** Field: id Type: bit(2) Null: YES Key: Default: NULL Extra: *************************** 2. row *************************** Field: gender Type: bit(1) Null: YES Key: Default: NULL Extra: 2 rows in set (0.00 sec) mysql> insert into test (id, gender) values (0, 0); Query OK, 1 row affected (0.00 sec) mysql> insert into test (id, gender) values (0, 1); Query OK, 1 row affected (0.00 sec) mysql> insert into test (id, gender) values (3, 0); Query OK, 1 row affected (0.00 sec) mysql> insert into test (id, gender) values (4, 1); ERROR 1406 (22001): Data too long for column 'id' at row 1 mysql> insert into test (id, gender) values (2, 3); ERROR 1406 (22001): Data too long for column 'gender' at row 1细节1:如果插入数值大于BIT类型的取值范围,MySQL 会直接进行报错,不让用户进行此操作。
mysql> create table test(id int, num bit(8)); Query OK, 0 rows affected (0.01 sec) mysql> insert into test (id, num) values (1, 0); Query OK, 1 row affected (0.01 sec) mysql> insert into test (id, num) values (1, 2); Query OK, 1 row affected (0.00 sec) mysql> insert into test (id, num) values (2, 97); Query OK, 1 row affected (0.01 sec) mysql> insert into test (id, num) values (2, 'a'); Query OK, 1 row affected (0.00 sec) mysql> select * from test; +------+------+ | id | num | +------+------+ | 1 | | | 1 | | | 2 | a | | 2 | a | +------+------+ 4 rows in set (0.00 sec)细节2:bit 字段在显示时,是按照 ASCII 码对应的值显示的。
2.2 整数类型 ---- TINYINT 类型
tinyint :1 字节整数,取值范围为 -128 ~ 127
mysql> create table test(id tinyint, num tinyint unsigned); Query OK, 0 rows affected (0.01 sec) mysql> insert into test (id, num) values (1, 2); Query OK, 1 row affected (0.00 sec) mysql> insert into test (id, num) values (127, 255); Query OK, 1 row affected (0.00 sec) mysql> insert into test (id, num) values (128, 2); ERROR 1264 (22003): Out of range value for column 'id' at row 1 mysql> insert into test (id, num) values (1, -1); ERROR 1264 (22003): Out of range value for column 'num' at row 1细节1:如果插入数据不在合法区间内,MySQL 服务端会直接禁止此操作。
细节2:如果不带 unsigned ,默认是有符号类型,否则是无符号类型,取值范围变为 0 ~ 255。
mysql> create table test(id tinyint, num tinyint unsigned); Query OK, 0 rows affected (0.01 sec) mysql> insert into test (id, num) values (3.2, 5.4); Query OK, 1 row affected (0.01 sec) mysql> select * from test; +------+------+ | id | num | +------+------+ | 3 | 5 | +------+------+ 1 row in set (0.00 sec) mysql> insert into test (id, num) values (3.2, 5.6); Query OK, 1 row affected (0.00 sec) mysql> select * from test; +------+------+ | id | num | +------+------+ | 3 | 5 | | 3 | 6 | +------+------+ 2 rows in set (0.00 sec)细节3:如果插入数据含有小数部分,MySQL 服务端会进行四舍五入得到整数再进行插入。
其余整数类型与 TINYINT 类型用法和特点一样,此处不再过多演示。
2.3 小数类型
2.3.1 浮点数 ---- FLOAT 类型
float(M, D) :M 表示数据位数,D 表示小数位数。
mysql> create table test(salary float(4, 2)); Query OK, 0 rows affected (0.00 sec) mysql> insert into test (salary) values (35.24); Query OK, 1 row affected (0.00 sec) mysql> insert into test (salary) values (-99.99); Query OK, 1 row affected (0.00 sec) mysql> insert into test (salary) values (99.99); Query OK, 1 row affected (0.00 sec) mysql> insert into test (salary) values (98.943); Query OK, 1 row affected (0.00 sec) mysql> insert into test (salary) values (98.945); Query OK, 1 row affected (0.01 sec) mysql> insert into test (salary) values (100); ERROR 1264 (22003): Out of range value for column 'salary' at row 1 mysql> insert into test (salary) values (100.00); ERROR 1264 (22003): Out of range value for column 'salary' at row 1 mysql> insert into test (salary) values (10); Query OK, 1 row affected (0.00 sec) mysql> insert into test (salary) values (10.0); Query OK, 1 row affected (0.00 sec) mysql> select * from test; +--------+ | salary | +--------+ | 35.24 | | -99.99 | | 99.99 | | 98.94 | | 98.94 | | 10.00 | | 10.00 | +--------+ 7 rows in set (0.00 sec)细节1:float(4,2)表示的范围是 -99.99 ~ 99.99
细节2:如果插入数据不再其取值范围内,MySQL 服务端会直接禁止此操作
细节3:MySQL 服务端对插入的数据会进行四舍五入
细节4:如果插入的数据,小数位数不足,MySQL 服务端会自动对其进行补 0
double 类型的用法和特点,基本与 float 一致,只是精度比 float 高。
2.3.2 定点数 ---- DECIMAL 类型
DECIMAL 是 MySQL 中用于存储精确小数的数据类型,也称为定点数类型。
decimal(M,D) :M 表示数据位数,D 表示小数位数。
float 的四个细节,decimal 完全遵循。
那为什么需要 DECIMAL 呢?
它与 FLOAT、DOUBLE 最大的区别在于:DECIMAL 用于精确存储十进制数,而 FLOAT、DOUBLE 属于近似数值类型。
因此,在金额、财务等要求小数精确的场景中,优先使用 DECIMAL。
2.4 文本/二进制类型
2.4.1 CHAR 类型
char(M) :定长字符串,其中 M 表示字符串能够存储的最大字符数
mysql> create table test(name char(5)); Query OK, 0 rows affected (0.01 sec) mysql> insert into test (name) values ('a'); Query OK, 1 row affected (0.00 sec) mysql> insert into test (name) values ('国庆节快乐'); Query OK, 1 row affected (0.00 sec) mysql> insert into test (name) values ('国庆节快乐!'); ERROR 1406 (22001): Data too long for column 'name' at row 1 mysql> select * from test; +-----------------+ | name | +-----------------+ | a | | 国庆节快乐 | +-----------------+ 2 rows in set (0.01 sec)细节1:如果插入字符串的字符数不在合法区间,MySQL 服务端会禁止此操作。
细节2:M 表示的是最大字符数,不是字节数。
细节3:即使实际字符串长度小于 M,但 MySQL 服务端依旧按照固定长度进行存储。对于不足指定长度的数据,MySQL 服务端存储时会使用空格进行右侧填充。
2.4.2 VARCHAR 类型
varchar(M):变长字符串,其中 M 同样表示能够存储到最大字符数
mysql> create table test(name varchar(5)); Query OK, 0 rows affected (0.01 sec) mysql> insert into test (name) values ('a'); Query OK, 1 row affected (0.00 sec)CHAR 类型的细节1和细节2,VARCHAR同样满足。
但是VARCHAR不会像CHAR一样都按照固定长度存储,而是根据实际字符串长度进行存储。
细节1:由于字符串长度不是固定的,MySQL 还需要额外使用 1 ~ 2 个字节记录字符串实际占用的字节数。
2.4.3 CHAR 和 VARCHAR 的区别
| 对比项 | CHAR(M) | VARCHAR(M) |
|---|---|---|
| 长度 | 定长 | 变长 |
| M 的含义 | 最大字符数 | 最大字符数 |
| 空间使用 | 按固定长度处理 | 根据实际数据长度变化 |
| 额外长度信息 | 不需要 | 需要 1~2 字节记录长度 |
| 适合场景 | 长度固定的数据 | 长度变化较大的数据 |
| 典型使用 | 性别、国家代码等 | 用户名、邮箱、地址等 |
2.5 日期时间类型
2.5.1 DATE 类型
DATE 占用三个字节,用于存储日期信息,只包含年、月、日。基本格式:YYYY-MM-DD
mysql> create table student(id int, name varchar(20), birthday date); Query OK, 0 rows affected (0.05 sec) mysql> insert into student (id, name, birthday) values (1, '张三', '2026-10-1'); Query OK, 1 row affected (0.02 sec) mysql> select * from student; +------+--------+------------+ | id | name | birthday | +------+--------+------------+ | 1 | 张三 | 2026-10-01 | +------+--------+------------+ 1 row in set (0.00 sec)常见应用场景:
- 出生日期
- 入学日期
- 商品生成日期
- 合同到期日期
2.5.2 DATETIME 类型
DATETIME 占用八个字节,用于存储日期和时间。基本格式:YYYY-MM-DD HH:MM:SS
mysql> create table article (id int, title varchar(100), create_time datetime); Query OK, 0 rows affected (0.01 sec) mysql> insert into article (id, title, create_time) values (1, 'CSDN', '2026-10-01 12:00:00'); Query OK, 1 row affected (0.00 sec) mysql> select * from article; +------+-------+---------------------+ | id | title | create_time | +------+-------+---------------------+ | 1 | CSDN | 2026-10-01 12:00:00 | +------+-------+---------------------+ 1 row in set (0.00 sec)常见应用场景:
- 文章发布时间
- 用户注册时间
- 订单创建时间
- 日志产生时间
2.5.3 TIMESTAMP 类型
TIMESTAMP占用四字节,表示时间戳。基本格式:YYYY-MM-DD HH:MM:SS
mysql> create table birthday (t1 date, t2 datetime, t3 timestamp); Query OK, 0 rows affected (0.01 sec) mysql> insert into birthday(t1,t2) values('2026-10-1','2026-10-1 12:1:1'); Query OK, 1 row affected (0.00 sec) mysql> select * from birthday; +------------+---------------------+---------------------+ | t1 | t2 | t3 | +------------+---------------------+---------------------+ | 2026-10-01 | 2026-10-01 12:01:01 | 2026-10-01 18:28:55 | +------------+---------------------+---------------------+ mysql> update birthday set t1='2026-10-2'; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from birthday; +------------+---------------------+---------------------+ | t1 | t2 | t3 | +------------+---------------------+---------------------+ | 2026-10-02 | 2026-10-01 12:01:01 | 2026-10-01 18:32:09 | +------------+---------------------+---------------------+细节1:插入数据时,会自动补上时间戳。
细节2:更新数据时,时间戳会自动更新为当前时间戳。
常见应用场景:
- 数据创建时间
- 最后修改时间
- 登录时间
- 操作记录
2.6 String 类型
ENUM 和 SET 都属于 MySQL 中的字符串类型。
它们的共同特点就是:字段能够保存的值需要在创建表时提前定义。
二者的核心区别:ENUM 只能选择一个值,而 SET 可以同时选择多个值。
2.6.1 ENUM 类型
ENUM 用于表示从多个候选值中选择一个值。
基本语法:enum('值1', '值2', '值3', ...)
mysql> create table user (id int, name varchar(20), gender enum('男', '女', '未知')); Query OK, 0 rows affected (0.01 sec) mysql> insert into user (id, name, gender) values (1, '张三', '男'); Query OK, 1 row affected (0.01 sec) mysql> insert into user (id, name, gender) values (2, '李四', '无'); ERROR 1265 (01000): Data truncated for column 'gender' at row 1 mysql> insert into user (id, name, gender) values (2, '李四', '女'); Query OK, 1 row affected (0.00 sec) mysql> select * from user; +------+--------+--------+ | id | name | gender | +------+--------+--------+ | 1 | 张三 | 男 | | 2 | 李四 | 女 | +------+--------+--------+ 2 rows in set (0.00 sec)细节1:要插入的值必须在 enum 的候选值中,否则 MySQL 服务端会禁止此操作。
2.6.2 SET 类型
SET 表示从候选值中同时选择零个或多个值。
基本语法:set('值1', '值2', '值3', ...)
mysql> create table user (id int, name varchar(20), hobby set('篮球', '足球', '编程', '游戏')); Query OK, 0 rows affected (0.03 sec) mysql> insert into user (id, name, hobby) values (1, '张三', '篮球,编程'); Query OK, 1 row affected (0.00 sec) mysql> insert into user (id, name, hobby) values (2, '李四', '足球'); Query OK, 1 row affected (0.00 sec) mysql> select * from user; +------+--------+---------------+ | id | name | hobby | +------+--------+---------------+ | 1 | 张三 | 篮球,编程 | | 2 | 李四 | 足球 | +------+--------+---------------+ 2 rows in set (0.00 sec)SET 同样遵循 ENUM 的细节1
2.6.3 ENUM 和 SET 的区别
| 对比项 | ENUM | SET |
|---|---|---|
| 中文含义 | 枚举 | 集合 |
| 候选值 | 创建字段时提前定义 | 创建字段时提前定义 |
| 可选择数量 | 只能选择一个 | 可以选择多个 |
| 返回形式 | 一个字符串 | 多个值以逗号分隔 |
| 常见场景 | 状态、等级等 | 权限、标签等 |
2.6.4 底层存储特点
ENUM 和 SET 虽然查询出来表现为字符串,但 MySQL 内部并不是简单地按照普通字符串来处理。
对于:
enum('男', '女', '未知')每个枚举成员都有对应的数字索引:
'男' → 1 '女' → 2 '未知' → 3而 SET 更像是通过位组合表示多个成员,例如:
'篮球' → 0001 '足球' → 0010 '编程' → 0100 '游戏' → 1000mysql> insert into user (id, name, hobby) values (2,'王五', 5); Query OK, 1 row affected (0.00 sec) mysql> select * from user; +------+--------+---------------+ | id | name | hobby | +------+--------+---------------+ | 1 | 张三 | 篮球,编程 | | 2 | 李四 | 足球 | | 2 | 王五 | 篮球,编程 | +------+--------+---------------+ 3 rows in set (0.00 sec)在插入时,我们也可以通过它们对应的字面值来进行插入。