CHAR_LENGTH函数返回字符数而非字节数,适用于中文等多字节字符;若CHAR_LENGTH('你好')返回4而非2,通常因字符集为latin1或utf8mb3导致乱码,需确认字段及连接编码为utf8mb4。

CHAR_LENGTH 函数在绝大多数主流 SQL 数据库中(如 MySQL、PostgreSQL、SQLite)返回的是字符数,不是字节数——这对中文处理很关键。但实际用起来,很多人发现结果仍不对,问题往往不出在函数本身,而在字符集或字段定义上。
为什么 CHAR_LENGTH('你好') 有时返回 4 而不是 2
最常见原因是列或连接的字符集被设成了 latin1 或 utf8mb3(MySQL 中旧式 utf8),导致中文被截断或存储为乱码字节序列。此时 CHAR_LENGTH 统计的是“错误解码后的字节串长度”,而非真实中文字符数。
- 确认表字段字符集:
SHOW CREATE TABLE your_table;,检查是否为utf8mb4 - 确认客户端连接编码:
SELECT @@character_set_client, @@collation_connection;(MySQL) - PostgreSQL 默认支持 UTF-8,但若客户端声明为
SQL_ASCII,也会出错
CHAR_LENGTH 和 LENGTH 的区别必须分清
CHAR_LENGTH 数字符,LENGTH 数字节。对中文而言,UTF-8 下一个汉字占 3 字节(utf8mb4 下最多 4 字节),所以两者数值差异直接暴露编码问题。
-
CHAR_LENGTH('你好')→ 正常应返回2 -
LENGTH('你好')→ 在utf8mb4下通常返回6(2×3)或8(含 emoji 等四字节字符) - 如果
CHAR_LENGTH('你好') = 4且LENGTH('你好') = 4,基本可断定字符串被当作了 latin1 处理
在 WHERE 条件或 ORDER BY 中安全使用 CHAR_LENGTH
直接写 WHERE CHAR_LENGTH(name) > 5 没问题,但要注意:该函数无法走索引(除非数据库支持函数索引,如 PostgreSQL 的表达式索引或 MySQL 8.0+ 的函数索引)。性能敏感场景下,别依赖它做高频过滤。
- MySQL 8.0+ 可建函数索引:
CREATE INDEX idx_name_len ON users ((CHAR_LENGTH(name))); - PostgreSQL 需显式创建:
CREATE INDEX idx_name_len ON users (CHAR_LENGTH(name)); - SQLite 不支持函数索引,只能靠应用层缓存或冗余字段(如单独存
name_len)
真正容易被忽略的点是:字符长度判断逻辑一旦嵌套在视图、存储过程或 ORM 的 raw query 里,很容易因连接层字符集不一致,让 CHAR_LENGTH 在不同环境返回不同结果——建议在建表时就强制统一 utf8mb4,并在应用配置中显式指定 charset,而不是依赖默认值。










