乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • 第1章 数据库基础与安装

    • MySQL 简介
    • MySQL 5.6 到 5.7 到 8.0 关键差异速查
    • 安装 MySQL 5.7
    • 连接与断开服务器
    • 创建数据库
    • 创建数据表
    • 数据库与数据表
    • 加载数据
    • 获取数据库信息
    • 批处理模式
    • SHOW 语句汇总
    • FLUSH 与 RESET 语句
    • my.cnf 核心参数
    • 字符集与排序规则
  • 第2章 SQL基础查询

    • SELECT
    • WHERE
    • ORDER BY
    • LIMIT
    • COUNT
    • 聚合函数
    • 比较运算符
    • 逻辑运算符
    • 算术运算符
    • 模式匹配
    • NULL 值处理
    • UPDATE
    • DELETE
    • REPLACE
    • SELECT INTO
  • 第3章 数据类型与运算符

    • 数值类型
    • 字符串类型
    • 日期时间类型
    • BIT 类型
    • ENUM 类型
    • SET 类型
    • JSON 类型
    • 类型转换
  • 第4章 函数与表达式

    • 字符串函数
    • 数值函数
    • 日期函数
    • 全文检索函数
  • 第5章 高级查询与子查询

    • JOIN
    • 子查询
    • UNION
    • GROUP BY
    • HAVING
    • DISTINCT
  • 第6章 表与索引

    • 数据定义语言
    • 修改表结构
    • 视图
    • 修改视图与检查选项
    • 外键
    • 索引
    • 唯一索引
    • 复合索引
    • 存储引擎对比
    • 分区表
    • 第一范式与第二范式
    • 第三范式与 BC 范式
    • 反范式设计
  • 第7章 存储过程与函数

    • 存储过程
    • 存储函数
    • 变量
    • 流程控制
    • 游标
    • 预处理语句
  • 第8章 事务与锁

    • 事务
    • 事务隔离级别
    • 锁机制
    • MVCC
    • 死锁专题分析
    • LOCK TABLES
    • XA 事务
  • 第9章 用户管理与安全

    • 用户管理
    • 权限管理
    • 角色
    • SQL 注入防范
  • 第10章 性能优化入门

    • 执行计划
    • 索引优化
    • 查询优化
    • 查询优化器提示
    • 慢查询日志
    • InnoDB 深入机制
    • InnoDB 专项优化
    • Performance Schema
    • sys Schema
  • 第11章 复制与高可用

    • 主从复制原理
    • 半同步复制配置
    • binlog 开启与 point-in-time 恢复
    • mysqldump 全库备份
    • mysqldump 单表与条件备份
    • mysqldump 恢复与导入
    • xtrabackup 全量热备
    • xtrabackup 准备与恢复
    • xtrabackup 增量与流式备份
  • 第12章 触发器与事件

    • 触发器
    • 事件调度器
  • 参考

    • MySQL 5.7 专业术语大全
    • MySQL 5.7 关键字与保留字大全

字符串类型

导学

字符串是数据库中最常见的数据类型之一。MySQL 5.7 提供多种字符串类型,选错会导致空间浪费、查询变慢,甚至数据截断。本节讲透每种类型的适用场景。

定义

字符串类型:用于存储文本数据的数据类型。MySQL 5.7 主要提供 CHAR、VARCHAR、TEXT、BLOB 及其变体。

CHAR vs VARCHAR

特性CHAR(M)VARCHAR(M)
存储方式定长,不足补空格变长,只存实际内容 + 1~2 字节长度前缀
最大长度255 字符65535 字节(受行大小限制)
检索效率固定长度,略快需读取长度前缀,略慢
空间效率短数据浪费空间按需存储,节省空间
尾部空格存储时补足,检索时去除保留尾部空格(5.7 行为)

存储差异演示

当前数据状态:

创建两张结构相同但类型不同的表:

CREATE TABLE char_demo (
    id INT PRIMARY KEY,
    code CHAR(10)
);

CREATE TABLE varchar_demo (
    id INT PRIMARY KEY,
    code VARCHAR(10)
);

INSERT INTO char_demo VALUES
(1, 'ABC');

INSERT INTO varchar_demo VALUES
(1, 'ABC');

验证存储差异:

SELECT
    id,
    code,
    LENGTH(code) AS length_val,
    CHAR_LENGTH(code) AS char_length_val
FROM char_demo;

结果:

idcodelength_valchar_length_val
1ABC33
SELECT
    id,
    code,
    LENGTH(code) AS length_val,
    CHAR_LENGTH(code) AS char_length_val
FROM varchar_demo;

结果:

idcodelength_valchar_length_val
1ABC33

结果解读:表面上检索出来的长度相同,是因为 CHAR 在检索时会自动去除尾部空格。如果插入时带有尾部空格,差异就会显现:

INSERT INTO char_demo VALUES (2, 'XYZ   ');
INSERT INTO varchar_demo VALUES (2, 'XYZ   ');

SELECT
    id,
    CONCAT('[', code, ']') AS wrapped_code,
    LENGTH(code) AS stored_length
FROM char_demo WHERE id = 2;

结果:

idwrapped_codestored_length
2[XYZ]3
SELECT
    id,
    CONCAT('[', code, ']') AS wrapped_code,
    LENGTH(code) AS stored_length
FROM varchar_demo WHERE id = 2;

结果:

idwrapped_codestored_length
2[XYZ ]6

结果解读:

  • CHAR(10) 存储 'XYZ ' 时,检索时尾部空格被去除,显示为 [XYZ],长度 3
  • VARCHAR(10) 存储 'XYZ ' 时,保留尾部空格,显示为 [XYZ ],长度 6
  • 这说明 CHAR 在存储时确实补了空格,只是在返回给客户端时去除了

SQL 建表示例

CREATE TABLE employees (
    emp_id INT PRIMARY KEY AUTO_INCREMENT,
    emp_name VARCHAR(20),
    dept VARCHAR(20),
    score DECIMAL(5,2)
);

INSERT INTO employees (emp_name, dept, score) VALUES
('大翔', '技术部', 100),
('白歌', '技术部', NULL);

当前表数据:

emp_idemp_namedeptscore
1大翔技术部100
2白歌技术部NULL

选型建议:

  • 长度固定或几乎固定:CHAR(如手机号、MD5 值、性别标志)
  • 长度变化大:VARCHAR(如姓名、地址、邮箱)
  • 最大长度:绝大部分场景用 VARCHAR,CHAR 只在明确定长时有优势

TEXT 类型家族

类型最大长度存储方式
TINYTEXT255 字节内联或溢出存储
TEXT65535 字节溢出存储(单独页)
MEDIUMTEXT16 MB溢出存储
LONGTEXT4 GB溢出存储

TEXT 与 VARCHAR 对比演示

当前数据状态:

CREATE TABLE article_text (
    article_id INT PRIMARY KEY,
    summary VARCHAR(255) COMMENT '摘要,较短',
    content TEXT COMMENT '正文,可能很长'
);

INSERT INTO article_text VALUES
(1, 'MySQL简介', 'MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,目前属于Oracle旗下产品。MySQL是最流行的关系型数据库管理系统之一,在WEB应用方面,MySQL是最好的RDBMS应用软件之一。');

操作语句:

SELECT
    article_id,
    summary,
    LENGTH(summary) AS summary_bytes,
    LEFT(content, 50) AS content_preview,
    LENGTH(content) AS content_bytes
FROM article_text;

操作后的数据状态:

article_idsummarysummary_bytescontent_previewcontent_bytes
1MySQL简介15MySQL是一个关系型数据库管理系统,由瑞典MySQL...137

结果解读:

  • summary 使用 VARCHAR(255),数据内联存储在行中,查询速度快
  • content 使用 TEXT,当数据较大时存储在独立的溢出页中,需要额外的 I/O 读取
  • TEXT 列不能完全利用内存中的行缓存,且某些操作(如内存排序)受限

关键认知:TEXT 列的数据通常存储在独立的溢出页中,不在行内。这会影响查询性能(需要额外的 I/O),且 TEXT 列不能完全利用内存中的行缓存。

BLOB 类型家族

BLOB(Binary Large Object)用于存储二进制数据,如图片、音频、文件等。类型与 TEXT 一一对应(TINYBLOB、BLOB、MEDIUMBLOB、LONGBLOB)。

重要建议:MySQL 可以存图片,但不建议。更好的做法是在 MySQL 中存文件路径,将实际文件存放在对象存储(OSS、S3)或文件系统中。

存路径 vs 存文件的对比演示

当前数据状态:

-- 不推荐:直接存图片
CREATE TABLE bad_design (
    image_id INT PRIMARY KEY,
    image_name VARCHAR(100),
    image BLOB  -- 图片塞进数据库,表膨胀,备份缓慢
);

-- 推荐:存文件路径
CREATE TABLE good_design (
    image_id INT PRIMARY KEY,
    image_name VARCHAR(100),
    image_url VARCHAR(500)  -- 如 https://cdn.example.com/img/123.jpg
);

INSERT INTO good_design VALUES
(1, 'logo.png', 'https://cdn.example.com/img/logo.png'),
(2, 'banner.jpg', 'https://cdn.example.com/img/banner.jpg');

当前 good_design 表数据:

image_idimage_nameimage_url
1logo.pnghttps://cdn.example.com/img/logo.png
2banner.jpghttps://cdn.example.com/img/banner.jpg

结果解读:存 URL 的优势:

  • 数据库备份和恢复速度不受影响
  • 图片可通过 CDN 分发,降低数据库负载
  • 对象存储成本通常低于数据库存储成本
  • 数据库只负责元数据管理,职责清晰

常见误区

误区正解
VARCHAR 比 CHAR 慢很多现代 MySQL 中差异极小,VARCHAR 的空间节省通常更有价值。
TEXT 和 VARCHAR 没区别TEXT 数据通常存在溢出页,查询需要额外 I/O;且 TEXT 有某些索引限制。
字符串长度以字节计VARCHAR(10) 在 utf8mb4 下最多存 10 个字符(可能占 40 字节),不是 10 字节。
VARCHAR 声明越大越好过大的声明会浪费内存(排序缓冲区按声明长度分配),且可能触发行大小限制。

面试考点

Q:CHAR 和 VARCHAR 的区别?

CHAR 定长,存储时不足长度补空格,适合长度固定的场景;VARCHAR 变长,只存实际内容加长度前缀,适合长度变化大的场景。MySQL 5.7 中绝大多数场景优先用 VARCHAR。

Q:VARCHAR(255) 有什么特殊意义?

VARCHAR(255) 及以下使用 1 字节存储长度前缀;VARCHAR(256) 及以上需要 2 字节。但这不是选择 255 的理由,应按实际业务需求声明长度。

Q:为什么不在数据库里存图片?

  1. 数据库备份和恢复时间暴增;2. 图片读写会污染缓冲池,影响正常查询性能;3. 对象存储(OSS/S3)成本更低、CDN 分发更快。数据库只存文件元数据和 URL。

小结

  • 短文本、定长文本用 CHAR,变长文本用 VARCHAR
  • 长文本(> 65535 字节)用 TEXT,二进制数据用 BLOB
  • TEXT/BLOB 通常存储在溢出页,查询性能差于 VARCHAR
  • 图片/文件应存 URL,不存数据库

下一章引子:除了文本,业务中另一类高频数据是日期和时间——注册时间、订单时间、有效期等。

上一页
数值类型
下一页
日期时间类型