MySQL 基础篇(三):一文掌握 MySQL 常见数据类型

目录

本文内容概要

一、常见数据类型分类

二、数值类型

[2.1 BIT 类型](#2.1 BIT 类型)

[2.2 整数类型 ---- TINYINT 类型](#2.2 整数类型 ---- TINYINT 类型)

[2.3 小数类型](#2.3 小数类型)

[2.3.1 浮点数 ---- FLOAT 类型](#2.3.1 浮点数 ---- FLOAT 类型)

[2.3.2 定点数 ---- DECIMAL 类型](#2.3.2 定点数 ---- DECIMAL 类型)

[2.4 文本/二进制类型](#2.4 文本/二进制类型)

[2.4.1 CHAR 类型](#2.4.1 CHAR 类型)

[2.4.2 VARCHAR 类型](#2.4.2 VARCHAR 类型)

[2.4.3 CHAR 和 VARCHAR 的区别](#2.4.3 CHAR 和 VARCHAR 的区别)

[2.5 日期时间类型](#2.5 日期时间类型)

[2.5.1 DATE 类型](#2.5.1 DATE 类型)

[2.5.2 DATETIME 类型](#2.5.2 DATETIME 类型)

[2.5.3 TIMESTAMP 类型](#2.5.3 TIMESTAMP 类型)

[2.6 String 类型](#2.6 String 类型)

[2.6.1 ENUM 类型](#2.6.1 ENUM 类型)

[2.6.2 SET 类型](#2.6.2 SET 类型)

[2.6.3 ENUM 和 SET 的区别](#2.6.3 ENUM 和 SET 的区别)

[2.6.4 底层存储特点](#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。

sql 复制代码
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 会直接进行报错,不让用户进行此操作。

sql 复制代码
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

sql 复制代码
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。

sql 复制代码
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 表示小数位数。

sql 复制代码
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 表示字符串能够存储的 最大字符数

sql 复制代码
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 同样表示能够存储到最大字符数

sql 复制代码
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

sql 复制代码
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

sql 复制代码
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

sql 复制代码
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', ...)

sql 复制代码
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', ...)

sql 复制代码
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 内部并不是简单地按照普通字符串来处理。

对于:

sql 复制代码
enum('男', '女', '未知')

每个枚举成员都有对应的数字索引:

复制代码
'男'    → 1
'女'    → 2
'未知'  → 3

而 SET 更像是通过位组合表示多个成员,例如:

复制代码
'篮球' → 0001
'足球' → 0010
'编程' → 0100
'游戏' → 1000
sql 复制代码
mysql> 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)

在插入时,我们也可以通过它们对应的字面值来进行插入。

相关推荐
青山木1 小时前
秒杀系统设计(一):需求拆解与流量治理
java·数据库·redis·后端·架构
lusklusklusk1 小时前
Oracle数据库基础之8_闪回
数据库·oracle
zhangrelay1 小时前
机器人或计算机智能与时间相关案例汇总(ROS2-ROS1)
linux·笔记·学习·ubuntu·机器人
沫璃染墨1 小时前
《从零入门Linux系统篇(五十三):线程篇·六——线程互斥详解:从并发问题到mutex互斥锁》
linux·运维·服务器·开发语言·后端·架构·系统架构
程序员-Benothing1 小时前
Shell循环教程:for、while、until、break、continue详解
linux·运维·服务器
lusklusklusk1 小时前
Oracle数据库基础之10_性能优化
数据库·oracle·性能优化
Omics Pro1 小时前
预测性虚拟细胞中显式机理算子
大数据·数据库·人工智能·python·算法·机器学习·自然语言处理
Zhang~Ling1 小时前
Linux网络:五种IO模型及其工作原理与应用
linux·网络·php
看浪的路人1 小时前
第5讲:Prompt 管理与版本追踪
大数据·数据库·elasticsearch