LENGTH返回字节长度,CHAR_LENGTH返回字符长度;UTF8MB4下汉字占3-4字节而字符数恒为1,故LENGTH常大于CHAR_LENGTH,影响存储、协议校验与索引性能。

LENGTH 返回字节长度,CHAR_LENGTH 返回字符长度
在 MySQL 中,LENGTH() 和 CHAR_LENGTH() 都能算字符串长度,但含义完全不同。如果你关心「这个字段实际占多少存储空间」或「是否超出 VARBINARY 限制」,必须用 LENGTH();如果只关心「有几个汉字/字母」,才该用 CHAR_LENGTH()。
根本原因在于 MySQL 的字符集处理方式:UTF8MB4 下,一个汉字占 3 或 4 字节,而 LENGTH() 按字节计数,CHAR_LENGTH() 按 Unicode 字符计数(无论多长)。
中文、emoji 场景下 LENGTH 明显大于 CHAR_LENGTH
执行这条语句就能直观看到差异:
SELECT
'你好?' AS str,
LENGTH('你好?') AS byte_len,
CHAR_LENGTH('你好?') AS char_len;
结果通常是:byte_len = 10(“你好”各 3 字节 + ? 占 4 字节),char_len = 3(两个汉字 + 一个 emoji 算一个字符)。
- 若字段定义为
VARCHAR(10),存得下这个字符串(字符数没超) - 但若底层是
VARBINARY(10)或做 HTTP header 截断逻辑,10 字节根本装不下 —— 这时只看CHAR_LENGTH()就会出错 - 某些旧系统用
LENGTH()做密码哈希前校验长度,UTF8MB4 下可能误判超长
PostgreSQL 和 SQL Server 不叫 CHAR_LENGTH
MySQL 的 CHAR_LENGTH() 在 PostgreSQL 里叫 CHAR_LENGTH()(同名),但 SQL Server 只有 LEN() —— 它的行为等价于 MySQL 的 CHAR_LENGTH(),不提供原生字节长度函数。SQL Server 要算字节长度得绕一下:
SELECT DATALENGTH(N'你好?'); -- 返回 10,注意必须用 N'' 前缀表示 Unicode
Oracle 用 LENGTHB() 表示字节长度,LENGTH() 默认是字符长度(和 MySQL 相反)。
- 跨数据库写迁移脚本时,别直接复制
LENGTH()—— 先确认目标库的默认语义 - MySQL 5.7+ 默认字符集是 utf8mb4,
LENGTH()的结果比老版本更“膨胀”,升级后要重测长度校验逻辑
WHERE 条件里混用 LENGTH 和 CHAR_LENGTH 可能导致索引失效
如果在 WHERE 子句里对字段套 LENGTH(col) > 10,即使 col 有索引,MySQL 通常也无法走索引(属于对列做函数运算)。而 CHAR_LENGTH(col) > 10 同样如此。
- 真要按长度过滤且需性能,建议加生成列:
ALTER TABLE t ADD COLUMN byte_len INT AS (LENGTH(str_col)) STORED,再给它建索引 - 或者业务层提前计算好长度存到单独字段,避免每次查都算
- 特别注意:JSON 字段用
LENGTH(json_col)返回的是整个 JSON 文本的字节数,不是里面某个 key 的值长度
实际用哪个,取决于你到底在约束什么:是磁盘空间、网络传输、协议限制(字节),还是用户感知、显示宽度、业务规则(字符)。两者差的那几个字节,常常就是线上截断、乱码、越界报错的源头。











