必须用CHAR_LENGTH(),因LENGTH()返回字节数而非字符数,utf8mb4下中文、emoji等多字节字符会导致长度误判;CHAR_LENGTH()按Unicode字符计数,与前端一致,适用于所有语言校验。

MySQL里用LENGTH()还是CHAR_LENGTH()?
直接说结论:过滤中文、emoji或带重音符号的字符时,必须用CHAR_LENGTH(),LENGTH()返回的是字节数,不是字符数。比如LENGTH('你好')在utf8mb4下返回6(每个汉字占3字节),而CHAR_LENGTH('你好')才返回2。
常见错误是写WHERE LENGTH(name) > 10后发现中文名被意外截断或漏掉——这说明你实际想比的是“几个字”,不是“占几字节”。
-
CHAR_LENGTH():按Unicode字符计数,适用于所有语言和符号 -
LENGTH():只适合纯ASCII场景,比如判断英文字段是否超长(如密码哈希值) - MySQL 8.0+ 支持
CHAR_LENGTH()作为标准SQL函数,兼容性更好
PostgreSQL中为什么LENGTH()能直接用?
PostgreSQL的LENGTH()默认按字符计数,不区分字节/字符,所以LENGTH('café') == 4,LENGTH('??') == 1(emoji算一个字符)。这点和MySQL不同,别套用经验。
但要注意:如果字段是bytea类型或用了octet_length(),那返回的就是字节数——这时候再用LENGTH()就可能出错。
- 字符串字段(
text、varchar)用LENGTH()安全 - 避免混用
octet_length()和LENGTH()做条件判断 - 排序或分组时,
LENGTH()结果稳定,不会因编码变化波动
SQL Server里LEN()会悄悄吃掉末尾空格
LEN()函数在SQL Server中自动忽略字符串末尾的空格,比如LEN('abc ')返回3,不是6。这在做精确长度校验时非常危险——你本想查“刚好5个字符且含空格”的数据,结果全被过滤掉了。
解决办法是改用DATALENGTH()并除以字符字节数:对varchar除以1,对nvarchar除以2(因为Unicode占2字节)。
- 要严格按显示长度过滤,用
DATALENGTH(col) / CASE WHEN TYPEOF(col) = 'nvarchar' THEN 2 ELSE 1 END -
LEN()适合快速估算,不适合校验格式(如身份证号18位、手机号11位) - 如果字段定义为
nvarchar但存了ASCII字符,DATALENGTH()仍按2字节/字符算,需确认业务是否接受
跨数据库写法怎么保持一致?
没有银弹函数,但可以用表达式模拟统一行为:把字符串前后各加一个非空字符,再减2。例如CHAR_LENGTH(CONCAT('x', col, 'x')) - 2能绕过SQL Server的LEN()截空格问题,也兼容MySQL/PostgreSQL。
不过代价是索引失效——CHAR_LENGTH()本身就不走索引,再套函数更慢。真要高频按长度查询,建议加计算列并建索引:
- MySQL:添加
ALTER TABLE t ADD COLUMN name_len TINYINT AS (CHAR_LENGTH(name)) STORED - PostgreSQL:用
GENERATED ALWAYS AS (LENGTH(name)) STORED - SQL Server:用
PERSISTED计算列 + 索引
字符集、字段类型、空格处理这三块最容易漏看,动笔写WHERE之前先SELECT CHAR_LENGTH(col), LENGTH(col), LEN(col)对比几行真实数据。

















