首页 / MySQL 入门教程 / 字符串数据类型

MySQL 入门教程

字符串数据类型

本教程共 46 篇 · 第 8 篇 · 更新于 2026-07-30 · 约 13 分钟阅读

MySQLMySQL 入门教程数据类型字符串CHARVARCHARTEXT变长

8. 字符串数据类型

本节目标:搞懂 CHAR 和 VARCHAR 的根本区别,知道什么时候用定长、什么时候用变长,理解 TEXT 系列的四个档位,学会按内容长度挑对字符串类型,避免空间浪费和截断。

字符串类型在建表里用得最多—用户名、邮箱、文章内容、状态码都是字符串。这一节把字符类型讲透,重点是 CHAR 和 VARCHAR 的取舍。

8.1 字符串类型一览

MySQL 的字符串类型主要分这几类:

类型用途最大长度
CHAR(M)定长字符串255 字符
VARCHAR(M)变长字符串65,535 字节(受行大小限制)
TINYTEXT短文本255 字节
TEXT普通文本65,535 字节
MEDIUMTEXT中等文本16 MB
LONGTEXT大文本4 GB
ENUM枚举(下节讲)-
SET集合(下节讲)-
Note

CHAR(M)VARCHAR(M) 里的 M字符数,不是字节数。比如 CHAR(30) 能存 30 个字符,无论是英文还是中文。具体占多少字节,取决于字符集(utf8mb4 下一个中文占 3~4 字节)。

8.2 CHAR:定长字符串

CHAR(M)定长类型。你定义 CHAR(10),不管存几个字符,永远占 10 个字符的空间。存不够就用空格在右边补齐

CREATE TABLE t (
    code CHAR(5)
);

INSERT INTO t VALUES('ab'), ('abcde');
  • 'ab',实际存的是 'ab '(后面补 3 个空格);
  • 'abcde',正好 5 个字符,原样存。

读取时,MySQL 会自动去掉尾部的空格,所以你存 'ab' 取出来还是 'ab'

CHAR 的适用场景

定长的特点决定了它适合长度固定或基本固定的数据:

  • 国家代码 'CN''US',用 CHAR(2)
  • 性别 'M'/'F',用 CHAR(1)
  • 手机号 11 位,用 CHAR(11)
  • 固定长度编码、状态码。

定长的优势是查询快:每行长度一样,MySQL 算偏移量很轻松,不用扫长度前缀。

Warning

CHAR 默认会去尾空格。如果开了 PAD_CHAR_TO_FULL_LENGTH SQL 模式,取出来才保留尾部空格。一般不用开。

8.3 VARCHAR:变长字符串

VARCHAR(M)变长类型。定义 VARCHAR(255),实际只占已存字符的长度 + 1~2 字节长度前缀。存多少占多少,不补空格。

CREATE TABLE users (
    id INT PRIMARY KEY,
    username VARCHAR(50),
    email VARCHAR(100)
);

INSERT INTO users VALUES(1, 'zhangsan', 'zs@example.com');

'zhangsan'(9 个字符),按 utf8mb4 算大约占 9~36 字节加 1 字节长度前缀,而不是占满 50 个字符的空间。

长度前缀

VARCHAR 用 1 或 2 字节记录实际长度:

  • 实际占用 ≤ 255 字节:1 字节前缀;
  • 实际占用 > 255 字节:2 字节前缀。

这部分是 MySQL 自动管的,你不用操心,知道有这个开销就行。

VARCHAR 的尾部空格

CHAR 不同,VARCHAR 保留尾部空格

CREATE TABLE t2 (v VARCHAR(5));
INSERT INTO t2 VALUES('ab   ');  -- 存 'ab' 加 3 个空格

mysql> SELECT v, LENGTH(v) FROM t2;
+------+-----------+
| v    | LENGTH(v) |
+------+-----------+
| ab   |         5 |
+------+-----------+

长度是 5,空格被保留下来了。但如果存的值加上尾部空格超过了定义长度,MySQL 会截断并给警告:

INSERT INTO t2 VALUES('abcde  ');  -- 7 个字符,超过 5
-- 实际存 'abcde',尾部空格被截断,1 个 warning

8.4 CHAR vs VARCHAR 怎么选

这是面试和实战的高频问题。核心区别:

对比项CHARVARCHAR
长度固定可变
存储占满定义长度实际长度 + 前缀
尾部空格存时补齐,取时去掉保留
查询速度略快略慢(要算长度)
空间浪费长度不一时浪费多几乎不浪费

选型建议:

  • 长度固定CHAR:编码、状态、性别、手机号;
  • 长度变化大VARCHAR:用户名、邮箱、标题、地址;
  • VARCHAR(255) 是最常用的”万金油”长度,大部分短文本都够。
Tip

别为了”安全”把所有字段都设成 VARCHAR(255) 或更长。长度设得太长,虽然实际存的少,但会影响索引(前缀索引)和内存排序缓冲。按业务合理预估长度。

8.5 VARCHAR 的最大长度限制

VARCHARM 理论最大是 65,535,但实际达不到,因为受行大小限制

MySQL 一行的所有列加起来不能超过 65,535 字节(不包括 BLOB/TEXT)。

看个例子,utf8mb4 下一个字符最多 4 字节:

-- 这样会失败:一个 VARCHAR 占满了整行
CREATE TABLE bad (
    s VARCHAR(16384)  -- 16384 × 4 = 65536,超了
) CHARACTER SET utf8mb4;
-- ERROR 1118: Row size too large

而且如果一行有多个 VARCHAR 列,它们加起来也不能超 65,535 字节。如果需要存超长文本,就该用 TEXT 系列。

Note

VARCHAR 的数据存在行内,超过 768 字节的部分可能溢出到外部页。这影响 InnoDB 的存储效率,所以超长字段别用 VARCHAR,用 TEXT

8.6 TEXT 系列:长文本专用

TEXT 是专门存长文本的类型,有四个档位:

类型最大长度用途
TINYTEXT255 字节极短文本
TEXT65,535 字节普通长文本,约 64 KB
MEDIUMTEXT16,777,215 字节中等文本,约 16 MB
LONGTEXT4,294,967,295 字节大文本,约 4 GB
CREATE TABLE articles (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(200),
    content MEDIUMTEXT
);

TEXT 和 VARCHAR 的区别

虽然都能存字符,但有几个关键不同:

  1. 存储位置TEXT 内容存在行外(外部页),行内只存指针;VARCHAR 存在行内;
  2. 默认值TEXT 不能有默认值(8.0 前),VARCHAR 可以;
  3. 索引TEXT 建索引必须指定前缀长度,VARCHAR 可以全列索引;
  4. 行大小TEXT 不算进行 65,535 字节限制。
Warning

不要拿 TEXT 存短内容。用户名、邮箱这种用 VARCHARTEXT 是给”文章正文""商品描述”这种超长文本用的。

8.7 字符串的长度怎么算

这一节是实战。MySQL 提供了两个长度函数:

  • LENGTH(s):返回字节数
  • CHAR_LENGTH(s):返回字符数

utf8mb4 下,中文一个字符占 3~4 字节,英文一个字符占 1 字节:

mysql> SELECT LENGTH('你好'), CHAR_LENGTH('你好');
+----------------+---------------------+
| LENGTH('你好') | CHAR_LENGTH('你好') |
+----------------+---------------------+
|              6 |                   2 |
+----------------+---------------------+

‘你好’ 是 2 个字符、6 个字节(utf8mb4 下中文占 3 字节)。

Tip

判断字符串长度时,要用 CHAR_LENGTH 不是 LENGTHLENGTH 数的是字节,中文会数成好几个,容易判断错。

8.8 ENUM 和 SET(下节细讲)

ENUMSET 也是字符串类型,但用法特殊:

  • ENUM('a','b','c'):枚举,只能取列表里的一个值;
  • SET('a','b','c'):集合,能取列表里的多个值。

比如订单状态 status ENUM('pending','paid','shipped','done')。这两个下一节和 JSON 一起细讲。

8.9 字符串类型选型建议

归纳几条实战经验:

  1. 定长用 CHAR,变长用 VARCHAR:这是第一原则;
  2. 短文本用 VARCHAR:用户名 VARCHAR(50)、邮箱 VARCHAR(100)、标题 VARCHAR(200)
  3. 长文本用 TEXT 系列:按预估大小选档,文章用 MEDIUMTEXT,超大的用 LONGTEXT
  4. 状态码用 CHAR(1) 或 ENUM:别用 VARCHAR 浪费;
  5. 手机号用 CHAR(11):定长,且不要参与数值运算;
  6. 别滥用超大长度VARCHAR(255) 够用就别写 VARCHAR(5000)
  7. 判断长度用 CHAR_LENGTH:数字符不数字节。

8.10 一个建表示例

把这一节学的串起来,建个规范的 users 表:

CREATE TABLE users (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL,
    email VARCHAR(100) NOT NULL,
    phone CHAR(11),
    age TINYINT UNSIGNED,
    bio VARCHAR(200),
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  • username/email/bio 变长,用 VARCHAR
  • phone 固定 11 位,用 CHAR(11)
  • ageTINYINT UNSIGNED
  • 字符集统一 utf8mb4

8.11 小结

这一节掌握了字符串类型:

  • CHAR(M) 定长,补空格、取时去空格,适合固定长度;
  • VARCHAR(M) 变长,保留尾部空格,适合长度变化大的文本;
  • VARCHAR 受行 65,535 字节限制,超长用 TEXT
  • TEXT 四档:TINYTEXT/TEXT/MEDIUMTEXT/LONGTEXT,存行外;
  • LENGTH 数字节,CHAR_LENGTH 数字符,判断长度用后者;
  • 选型核心:定长用 CHAR、变长用 VARCHAR、超长用 TEXT。

下一节讲日期与时间类型,这是另一类容易出错的数据类型。