char_length()返回字符数而非字节数,适用于用户感知长度校验;length()返回字节数,受编码影响;处理中文、emoji等需用char_length(),且注意其性能与空格计数特性。

CHAR_LENGTH() 返回字符数,不是字节数
MySQL 里 CHAR_LENGTH() 算的是字符串包含多少个字符,和编码无关。比如一个中文汉字、一个英文字母、一个 emoji,在 utf8mb4 下都算 1 个字符。这和 LENGTH() 完全不同——后者返回的是字节数,同一个字符串在不同编码下结果可能变。
常见错误是把 LENGTH() 当成“长度函数”用,结果在处理中文或 emoji 时出错:比如 LENGTH('你好') 在 utf8mb4 下返回 6(每个汉字占 3 字节),而 CHAR_LENGTH('你好') 才是预期的 2。
- 需要按“用户感知的长度”做校验(如用户名最多 20 个字符)→ 用
CHAR_LENGTH() - 需要判断存储开销或做底层字节切分 → 才考虑
LENGTH() - 字段定义为
VARCHAR(255),实际能存多少个字符,取决于CHAR_LENGTH()是否超限,不是LENGTH()
CHAR_LENGTH() 和 LENGTH() 在 utf8mb4 下差异明显
utf8mb4 是 MySQL 8.0 默认字符集,支持 4 字节字符(比如大多数 emoji)。这时候 CHAR_LENGTH() 和 LENGTH() 的差值会直接暴露问题。
例如:
SELECT CHAR_LENGTH('??'), LENGTH('??');
返回分别是 1 和 19(具体字节数取决于 emoji 实现,但一定远大于 1)。如果用 LENGTH() 做前端输入限制,用户发个 ?? 就可能被截断或报错。
- 建表时若指定了
CHARACTER SET utf8mb4,必须默认按CHAR_LENGTH()理解“长度” - 迁移旧系统时,如果原来用
LENGTH()做长度判断,切到 utf8mb4 后要重点检查校验逻辑 -
CHAR_LENGTH(NULL)返回NULL,不是 0,参与比较前注意判空
在 WHERE 或 ORDER BY 中用 CHAR_LENGTH() 要小心性能
CHAR_LENGTH() 是标量函数,用在 WHERE 条件里无法走索引(除非是生成列 + 函数索引)。比如 WHERE CHAR_LENGTH(name) > 10,哪怕 name 有索引,也会全表扫描。
- 真要高频按长度过滤,建议加一个生成列:
name_len TINYINT AS (CHAR_LENGTH(name)) STORED,再给它建索引 - 排序场景如
ORDER BY CHAR_LENGTH(title),数据量大时延迟明显,可提前计算并缓存长度值 - 避免在 JOIN ON 条件里套
CHAR_LENGTH(),容易让优化器放弃使用索引
CHAR_LENGTH() 对空格和控制字符也计数
CHAR_LENGTH() 统统按字符算,不忽略首尾空格,也不跳过 \t、\n、\r 这类控制字符。比如 CHAR_LENGTH(' a ') 是 3,CHAR_LENGTH("a\tb") 是 3。
如果你实际想“去掉空格后算长度”,得显式组合:
CHAR_LENGTH(TRIM(name))
- 前端传来的字符串常带首尾空格,直接
CHAR_LENGTH()可能导致校验宽松(比如允许 ' ' 通过长度为 0 的检查) - JSON 字段里提取的字符串可能含不可见字符,
CHAR_LENGTH()会如实反映,调试时可用HEX()辅助查看 - 正则匹配前若没清理空白,
CHAR_LENGTH()结果可能误导你对内容结构的判断











