length() 返回字节数,char_length() 返回字符数;utf8mb4下汉字占3或4字节,emoji可能更多;混用二者易致校验错乱、索引失效等问题。

LENGTH() 返回字节数,CHAR_LENGTH() 返回字符数
根本原因在于:MySQL 把「存储空间占用」和「人类可读单位」分开了。LENGTH() 数的是底层存了几个 byte,而 CHAR_LENGTH() 数的是你眼睛看到的几个「字」——不管它是 a、中 还是 ?,都算 1。
UTF8MB4 下一个汉字占 3 或 4 字节,不是固定值
很多人记成「汉字 = 3 字节」,这是过时经验。在 MySQL 5.7+ 默认的 utf8mb4 字符集里:
-
你、好等常用汉字通常占 3 字节 - 部分生僻字、古汉字、扩展区汉字(如 U+3400–U+4DBF)占 4 字节
- emoji 如
?、??可能占 4 字节甚至更多(含 ZWJ 序列)
所以 LENGTH('你好') 可能是 6,也可能是 7 或 8;而 CHAR_LENGTH('你好') 永远是 2。
混用 LENGTH 和 CHAR_LENGTH 会直接导致业务逻辑错乱
典型翻车场景:
- 用
LENGTH(nickname) 做昵称长度校验 → 用户输 <code>数据库(3 字)就超限,输abcde(5 字)却放过 - 前端用 JS 的
'你好'.length(= 2)做限制,后端却用LENGTH()校验 → 前后端永远对不上 - WHERE 中写
LENGTH(title) > 100→ 即使title有索引,MySQL 也无法使用(函数操作导致索引失效)
真正该用 LENGTH() 的地方极少:比如预判插入会不会触发 ERROR 1406(字段字节超限),或对接二进制协议要求精确字节数。
查字段是否含中文/emoji,别只看 LENGTH != CHAR_LENGTH
这个技巧常用,但有陷阱:
- ✅
LENGTH(name) != CHAR_LENGTH(name)能找出含多字节字符的记录(如中文、emoji) - ❌ 不能反推:
LENGTH(name) == CHAR_LENGTH(name)不代表全是 ASCII —— 比如两个 2 字节字符(GBK 编码下)也会相等 - ⚠️ 连接字符集影响结果:
SELECT @@character_set_client必须是utf8mb4,否则字符串字面量可能被错误转码,让LENGTH()返回意外值
最稳的方式是结合字符集确认 + 显式测试样本,而不是单靠一个不等式下结论。











