业务校验必须用CHAR_LENGTH(),因LENGTH()按字节数计算,utf8mb4下汉字占3字节、emoji占4字节,导致长度限制失效;CHAR_LENGTH()按Unicode码点计数,与前端语言一致,是日常唯一应使用的函数。

业务校验必须用 CHAR_LENGTH(),LENGTH() 只适合查字节开销或做底层截取——两者在 utf8mb4 下结果常差 2–4 倍,混用会直接导致长度限制失效。
为什么 LENGTH() 返回的不是“看起来有几个字”
LENGTH() 算的是字节数,完全取决于当前连接和字段的字符集。utf8mb4 下一个汉字占 3 字节(如‘你’)、emoji 占 4 字节(如‘’),所以 LENGTH('你好') 返回 6,LENGTH('') 返回 4。而前端 JS 的 str.length、Python 的 len() 都是按 Unicode 码点计数,值为 2 和 1。一旦用 LENGTH() 做用户名长度校验(比如 WHERE LENGTH(name) > 10),实际可能放过 3 个 emoji + 1 个字母(总字节 4×3+1=13),却拦下 4 个汉字(4×3=12)——人眼和逻辑全对不上。
- 执行
SELECT @@character_set_client, @@collation_connection;确认当前连接字符集,它会影响LENGTH()对字面量的解析 - 建表时若字段定义为
VARCHAR(255) CHARACTER SET latin1,LENGTH()最大能到 255;但改成utf8mb4后,同样定义最多存 63 个 4 字节字符(63×4=252),LENGTH()就永远 ≤252 -
SHOW CREATE TABLE table_name查字段真实字符集,别信建表语句里没显式声明的“默认值”
什么时候非用 LENGTH() 不可
只有两类场景绕不开 LENGTH():一是判断是否超出列的物理存储上限,二是配合 SUBSTRING() 或 LEFT() 按字节截断(极少见)。比如字段是 VARCHAR(100) CHARACTER SET utf8mb4,你想确保插入不报错,就得用 LENGTH() 判断字节是否 ≤100;又比如日志系统要硬截断二进制安全字符串,也得按字节切,否则可能把一个多字节字符从中间劈开,存进去变成乱码。
MySQL 数据库管理技能,能够通过自然语言查询和管理数据库,支持 SELECT/INSERT/UPDATE/DELETE、表管理、备份恢复等操作。当用户提及 MySQL、数据库查询、建表或数据备份时使用此技能。
-
INSERT INTO t (name) SELECT LEFT(name, 100) FROM src;这里的LEFT()默认按字符截,但若想严格控字节,得写成LEFT(name, 100)并确认连接字符集稳定 - 主从同步或备份还原时,若主库用
utf8mb4、从库误配成utf8(非 mb4),LENGTH()查询结果会突变,而CHAR_LENGTH()不受影响 -
ORDER BY LENGTH(name)排序的结果是“谁占空间多”,不是“谁字多”,搜索结果排序容易误导运营同学
CHAR_LENGTH() 是日常唯一该用的函数
CHAR_LENGTH()(等价于 CHARACTER_LENGTH())返回 Unicode 字符个数,和 JS、Python、Java 的字符串长度行为一致。用户昵称限 10 字、短信内容统计 70 字、JSON 字段内校验 key 长度,全部应该无条件用它。它不受字符集切换影响:CHAR_LENGTH('€') 在 latin1、utf8、utf8mb4 下都是 1;CHAR_LENGTH('') 在所有支持 emoji 的字符集下都是 1。
- 用
LENGTH(col) != CHAR_LENGTH(col)快速筛出含中文/emoji 的记录,比正则更轻量 - PostgreSQL 的
LENGTH()行为等同于 MySQL 的CHAR_LENGTH(),跨库迁移时如果代码里混用了LENGTH(),必须全局替换 - SQL Server 的
LEN()也按字符数,但会忽略末尾空格;MySQL 的CHAR_LENGTH()保留空格,对比时要注意空格处理逻辑是否一致
最易被忽略的一点:CHAR_LENGTH() 统计的是 Unicode 码点,不是“人眼一瞥觉得是一个字”的图形单元。像带修饰符的 emoji ‘??’(女人+肤色+发型)在 Unicode 中是多个码点,CHAR_LENGTH() 返回 3 或 4,不是 1。真要按显示单元计数,得上 ICU 库或应用层处理——数据库层做不到。

















