当我们思考在 MySQL 中存储文本时,VARCHAR
和 TEXT
往往是首先想到的。但 MySQL 8 的字符世界远不止于此,它提供了更多精细化的工具,以应对不同的存储需求。
![图片[1]-**MySQL 8 字符类型揭秘:超越 `VARCHAR` 与 `TEXT`,探索 `CHAR`、`ENUM` 与二进制的威力!**](https://share.0f1.top/wwj/site/soft/2025/06/19/20250619114347732.webp)
一、 定长与变长字符类型 (Character String Types)
这类是我们最常用来存储可读文本的类型,它们会受到字符集(Character Set)和排序规则(Collation)的影响。
1. CHAR(M)
– 定长字符串
CHAR
是 VARCHAR
的“兄弟”,但性格截然不同。VARCHAR
是“需要多少用多少”(在规定范围内),而 CHAR
则是“不管用多少,都占这么多”。
- 定义:
CHAR(M)
,M
代表你希望存储的字符数,范围是 0 到 255。 - 核心特点:
- 定长存储: 无论你实际存入的字符有多少,它都会占用
M
个字符的存储空间。如果存入的字符串长度小于M
,MySQL 会在右侧用空格填充以达到指定长度。 - 自动裁剪: 在检索时,这些尾部的填充空格通常会被自动删除(除非启用了
PAD_CHAR_TO_FULL_LENGTH
SQL 模式)。
- 定长存储: 无论你实际存入的字符有多少,它都会占用
- 何时使用
CHAR
?- 长度固定或几乎不变的数据: 如邮政编码
CHAR(6)
、性别CHAR(1)
(M/F)、国家代码CHAR(2)
(如 ‘US’, ‘CN’)、MD5 哈希值CHAR(32)
。 - 追求极致性能的短字符串: 因为长度固定,处理起来比变长的
VARCHAR
稍微快一点,尤其是在更新操作时,因为它不会导致行记录长度的改变。
- 长度固定或几乎不变的数据: 如邮政编码
示例:
CREATE TABLE users ( user_id INT, country_code CHAR(2) );
INSERT INTO users VALUES (1, 'CN');
-- 数据库中实际存储的是 'CN',虽然只占2个字符,但分配了2个字符的空间。
2. TINYTEXT
, MEDIUMTEXT
, LONGTEXT
– TEXT
家族的其他成员
TEXT
实际上是一个家族,除了基础的 TEXT
类型,还有其他三个兄弟,它们的区别仅在于最大存储容量。
TINYTEXT
: 最大长度为 255 (28−1) 个字符。TEXT
: 最大长度为 65,535 (216−1) 个字符(约 64KB)。MEDIUMTEXT
: 最大长度为 16,777,215 (224−1) 个字符(约 16MB)。LONGTEXT
: 最大长度为 4,294,967,295 (232−1) 个字符(约 4GB)。
核心用途:
TINYTEXT
: 存储简短的描述、备注等,长度超过VARCHAR(255)
但又不需要TEXT
那么大的情况。MEDIUMTEXT
: 存储较长的文章、JSON文档、日志内容等。LONGTEXT
: 存储极其巨大的文本数据,如书籍全文、大型日志文件、Base64 编码的资源等。
二、 集合类型 (Set Types)
这是 MySQL 提供的两种非常特殊的字符串类型,它们将值限制在一个预定义的集合中。
1. ENUM
– 枚举(单选)
ENUM
类型允许你从一个预定义的列表中只选择一个值。
- 定义:
ENUM('value1', 'value2', 'value3', ...)
- 核心特点:
- 单选: 一个
ENUM
列只能存储列表中的一个成员。 - 高效存储: 内部实际上存储的是值的数字索引(从1开始),而不是字符串本身。这非常节省空间。例如,
ENUM('Small', 'Medium', 'Large')
,’Medium’ 实际存储为数字2
。 - 可读性强: 查询时返回的是易于理解的字符串值,而不是数字索引。
- 单选: 一个
- 何时使用
ENUM
?- 当一个字段的值是固定的、有限的几个选项之一时。例如,订单状态
ENUM('PENDING', 'PROCESSING', 'SHIPPED', 'CANCELLED')
、用户等级ENUM('BRONZE', 'SILVER', 'GOLD', 'PLATINUM')
。
- 当一个字段的值是固定的、有限的几个选项之一时。例如,订单状态
示例:
CREATE TABLE orders ( order_id INT, status ENUM('PENDING', 'SHIPPED') );
INSERT INTO orders VALUES (101, 'PENDING');
-- 存储高效,但查询结果直观
2. SET
– 集合(多选)
SET
类型允许你从一个预定义的列表中选择零个或多个值。
- 定义:
SET('value1', 'value2', 'value3', ...)
- 核心特点:
- 多选: 可以存储列表中任意数量的成员组合,成员间用逗号分隔。
- 位图存储: 内部使用位(bit)来存储。每个预定义成员对应一个位。如果一个
SET
有 8 个成员,它就用一个字节存储。这比用逗号分隔的VARCHAR
字符串要高效得多。
- 何时使用
SET
?- 当一个字段可以有多个属性或标签时。例如,用户偏好
SET('Music', 'Sports', 'Reading', 'Travel')
、文章标签SET('Tech', 'Life', 'Finance')
。
- 当一个字段可以有多个属性或标签时。例如,用户偏好
示例:
CREATE TABLE user_profiles ( user_id INT, preferences SET('Music', 'Sports', 'Reading') );
INSERT INTO user_profiles VALUES (1, 'Music,Reading');
-- 使用 FIND_IN_SET() 函数可以方便地查询
SELECT * FROM user_profiles WHERE FIND_IN_SET('Music', preferences);
三、 二进制字符串类型 (Binary String Types)
与常规字符类型不同,二进制字符串类型存储的是字节序列(byte strings),而不是字符序列(character strings)。它们没有字符集的概念,比较和排序都基于字节的数值。
1. BINARY(M)
和 VARBINARY(M)
它们分别对应 CHAR(M)
和 VARCHAR(M)
,但用于存储二进制数据。
BINARY(M)
: 定长的二进制字符串。如果存入的数据不足M
字节,会用\0
(空字节) 在右侧填充。VARBINARY(M)
: 变长的二进制字符串。
核心用途:
- 存储固定长度的二进制数据,如 UUID(当以二进制格式存储时,
BINARY(16)
比CHAR(36)
高效得多)、加密哈希值。 - 当你需要进行严格的、区分大小写的字节比较时。
2. TINYBLOB
, BLOB
, MEDIUMBLOB
, LONGBLOB
BLOB
(Binary Large Object) 家族对应 TEXT
家族,用于存储大量的二进制数据。
TINYBLOB
: 最大 255 字节。BLOB
: 最大 65,535 字节(约 64KB)。MEDIUMBLOB
: 最大 16,777,215 字节(约 16MB)。LONGBLOB
: 最大 4,294,967,295 字节(约 4GB)。
核心用途:
- 存储图片、音频、视频文件、PDF文档、序列化的对象等任何非文本数据。
总结:如何选择?
类型 | 核心特点 | 核心场景 |
---|---|---|
CHAR | 定长,右侧空格填充 | 国家代码、MD5值、邮编等定长标识符 |
TEXT 家族 | 存储超长文本 | 文章内容、日志、长篇描述 |
ENUM | 单选列表,高效存储 | 订单状态、用户等级、类型分类 |
SET | 多选列表,位图存储 | 用户偏好、文章标签、权限集合 |
BINARY / VARBINARY | 字节串,区分大小写 | UUID、二进制哈希值 |
BLOB 家族 | 存储大型二进制对象 | 图片、音频、文件 |
通过理解这些类型的细微差别,你可以构建出结构更优、性能更好、数据更准确的数据库。不要再局限于 VARCHAR
和 TEXT
,让你的数据找到最合适的“家”。