length()返回字节长度,char_length()返回字符个数;前者受字符编码影响(如utf8mb4中中文占3字节、emoji占4字节),后者按unicode字符计数且结果恒定。

LENGTH() 返回字节长度,CHAR_LENGTH() 返回字符个数
MySQL 里 LENGTH() 和 CHAR_LENGTH() 看似相似,但底层逻辑完全不同。前者按字节计数,后者按 Unicode 字符计数。在 utf8mb4 字符集下,一个 emoji(如 ?)占 4 字节,但只是 1 个字符 —— 这时 LENGTH() 返回 4,CHAR_LENGTH() 返回 1。
中文、emoji、生僻字场景下 LENGTH() 容易误判字段实际长度
当你要校验用户昵称是否超长(比如限制 20 个字符),如果用 LENGTH(nickname) > 20,就会把一个 5 字的昵称(含 2 个 emoji)错误截断或拒绝:因为它的字节数可能是 5 × 3 + 2 × 4 = 23,明明才 7 个字符却触发了“超长”。
- 存储层用
TEXT或VARCHAR(255)时,长度限制是字符数,不是字节数 - 前端输入限制、后端参数校验、日志截断等逻辑,应统一用
CHAR_LENGTH()对齐语义 -
LENGTH()更适合排查乱码、BLOB 内容大小、网络传输开销估算等低层场景
CHARSET 和 COLLATION 影响 LENGTH() 的结果,但不影响 CHAR_LENGTH()
CHAR_LENGTH() 始终返回 Unicode 码点数量,与字符集无关;而 LENGTH() 的结果依赖当前列或字符串的字符集编码方式。例如:
SELECT
LENGTH('你好') AS len,
CHAR_LENGTH('你好') AS charlen,
CHARSET('你好') AS cs;
在 utf8mb4 下,len 是 6(每个汉字 3 字节),charlen 是 2;若该字符串被隐式转成 latin1(比如连接未设 charset),LENGTH() 可能变成 2(? 替换后单字节),但 CHAR_LENGTH() 仍是 2 —— 它不关心内容是否有效,只数“有多少个字符位置”。
ORDER BY 和 GROUP BY 中混用 LENGTH() 可能导致意外交互
排序或分组时若基于 LENGTH(col),同一逻辑含义的字符串(如 'a' 和 'á')可能因编码差异产生不同字节数,在 utf8mb4_general_ci 下它们本该等价,但 LENGTH() 不参与 collation 规则,纯看编码字节。这会让分组结果不稳定、排序顺序反直觉。
- 需要按“视觉长度”或“输入长度”归类时,优先用
CHAR_LENGTH(col) - 若必须用字节长度做索引优化(如前缀索引),确认字段字符集固定且无多字节字符干扰
- WHERE 条件中用
LENGTH(col) = N匹配特定编码结构(如固定长度 token)时,务必注明字符集假设
真正容易被忽略的是:很多 ORM 或中间件对字符串长度的默认判断会悄悄调用 LENGTH()(尤其旧版本),而不是你写的 CHAR_LENGTH() —— 查文档、看生成 SQL、必要时强制指定函数,比事后 debug 字符截断更省时间。











