CHAR_LENGTH 返回的是字符数,不是字节数;它对中、英文、数字、符号均计为1个字符,而 LENGTH 返回字节长度,中文在 utf8mb4 下占3–4字节。

CHAR_LENGTH 返回的是字节数还是字符数?
CHAR_LENGTH 返回的是**字符数(character count)**,不是字节数。它对中文、英文、数字、符号一视同仁,每个 Unicode 字符都算 1。这和 LENGTH(MySQL 中)或 DATALENGTH(SQL Server)有本质区别——后者返回的是字节长度,中文在 utf8mb4 下占 3 或 4 字节,会导致结果翻倍。
为什么有时候 CHAR_LENGTH(‘你好’) 返回 2,有时候却返回 6?
这基本说明你误用了 LENGTH 而非 CHAR_LENGTH。常见错误场景:
- 复制了别人用
LENGTH查字节的示例,但自己需要的是字符数 - 数据库连接未声明字符集(如没设
SET NAMES utf8mb4),导致客户端把 UTF-8 编码的中文传成乱码再计算,结果不可靠 - 字段定义是
latin1但存了 UTF-8 编码的字节流(典型双编码),CHAR_LENGTH仍会按“当前列字符集解释后的字符数”计算,但结果已失真
确保 CHAR_LENGTH 对中文准确的前提条件
三个关键点缺一不可:
- 表字段字符集必须是
utf8mb4(不是utf8,后者不支持 emoji 和部分生僻汉字) - 连接层字符集要对齐:执行
SET NAMES utf8mb4或在连接字符串中指定charset=utf8mb4 - 客户端输入本身是合法 UTF-8 字符串(比如 Python 的
str、Java 的String,而非已损坏的bytes)
验证方式:SELECT CHARSET('你好'), COLLATION('你好'); 应返回 utf8mb4 和对应排序规则。
CHAR_LENGTH 在 WHERE 和 ORDER BY 中的实际用法
它常用于长度约束或排序,但要注意隐式类型转换和性能影响:
- 过滤 4 字以上中文标题:
WHERE CHAR_LENGTH(title) > 4—— 可走索引仅当该列上有函数索引(MySQL 8.0+ 支持CREATE INDEX idx_len ON t ((CHAR_LENGTH(title)))) - 按名称字符长度排序:
ORDER BY CHAR_LENGTH(name)—— 没索引时会触发 filesort,大数据量慎用 - 别写成
CHAR_LENGTH(name) = LENGTH(name)来“判断是否全英文”,这在 utf8mb4 下永远为 false(因为中文字符的CHAR_LENGTH是 1,LENGTH是 3/4)
真正想区分中英文混合,得用正则:name REGEXP '[\x{4e00}-\x{9fff}]'(MySQL 8.0+ 支持 Unicode 属性)。
最常被忽略的是连接字符集配置——哪怕表结构完全正确,只要客户端连进来用的是 latin1,CHAR_LENGTH 算的就不是你看到的那个中文字符串。











