CHAR_LENGTH在UTF8MB4环境下对中文字符可靠,返回字符数而非字节数;若任一层(库、表、连接)字符集非utf8mb4,则结果失准,需三方同步配置。

CHAR_LENGTH 函数在中文场景下是否可靠
直接说结论:CHAR_LENGTH 在绝大多数现代 MySQL(5.7+)和 PostgreSQL 中,对中文字符返回的是「字符数」而非「字节数」,前提是数据库使用的是 UTF8MB4 字符集且连接也声明了 UTF8MB4。它能正确统计中文、emoji、日文假名等 Unicode 字符个数——但前提是环境没被“悄悄降级”。
为什么有时 CHAR_LENGTH 返回值比预期小
常见错误现象:CHAR_LENGTH('你好') 返回 2(正确),但实际却返回 4 或 1 —— 这基本锁定是字符集配置问题。
- 服务器默认字符集是
latin1或utf8(MySQL 的旧版伪 UTF8,不支持 4 字节字符)时,中文会被截断或转成 ?,CHAR_LENGTH统计的是乱码后的字节数或替换符个数 - 客户端连接未指定
charset=utf8mb4,即使表是 utf8mb4,数据传入时已损坏 - 字段定义为
TEXT但用CONVERT(... USING latin1)强转过,破坏原始编码
验证和修复字符集链路的三步检查
别猜,直接查。一条 SQL 不够,得看三层:
- 查库级字符集:
SHOW VARIABLES LIKE 'character_set_database';—— 应为utf8mb4 - 查表/字段字符集:
SHOW CREATE TABLE your_table;—— 确认字段含CHARACTER SET utf8mb4 - 查当前连接编码:
SHOW VARIABLES LIKE 'character_set_client';和SHOW VARIABLES LIKE 'collation_connection';—— 二者都应为utf8mb4_*开头
任一环节不是 utf8mb4,CHAR_LENGTH 就可能失准。修复需同步改库、表、连接三方配置,光改表没用。
CHAR_LENGTH vs LENGTH:中文统计必须用前者
LENGTH 返回字节数,CHAR_LENGTH 返回字符数。中文在 utf8mb4 下占 3 字节(常用汉字)或 4 字节(如 ?、?),用 LENGTH 会把一个汉字算成多个单位。
SELECT
'你好' AS str,
CHAR_LENGTH('你好') AS char_len, -- 返回 2
LENGTH('你好') AS byte_len; -- 返回 6(utf8mb4 下每个汉字 3 字节)如果业务逻辑依赖「用户输入多少个字」(比如评论限 100 字),必须用 CHAR_LENGTH;若做底层存储估算,才看 LENGTH。混用会导致前端显示 2 字、后端校验说超长——这种 bug 很难复现,因为只在特定字符(如生僻字、emoji)上触发。
真正容易被忽略的点:应用层连接池(如 HikariCP、SQLAlchemy)常会覆盖连接字符集设置,即使 MySQL 配置全对,代码里没显式指定 characterEncoding=utf8mb4,照样出错。

















