PostgreSQL中LENGTH()统计字符数,等价于CHAR_LENGTH();OCTET_LENGTH()才返回字节数。例如'你好'的LENGTH为2、OCTET_LENGTH为6,UTF-8下中文字符占3字节。

PostgreSQL里LENGTH()和OCTET_LENGTH()到底算什么
PostgreSQL的LENGTH()默认按**字符数**统计,和CHAR_LENGTH()完全等价;而OCTET_LENGTH()才真正返回**字节数**。两者在UTF-8环境下差异明显:一个中文字符占3字节,LENGTH('你好')返回2,OCTET_LENGTH('你好')返回6。
常见错误现象:WHERE LENGTH(content) > 100本意是“超100字符”,但误以为是“超100字节”,结果过滤过严;反过来若想查BLOB混入(比如意外存了二进制数据),用LENGTH()就完全失效。
- 业务上要校验用户昵称≤10个汉字?用
LENGTH(nickname) - 排查某字段是否被写入非文本内容(如PDF片段)?用
OCTET_LENGTH(raw_data) != LENGTH(raw_data) - 空格和控制符都参与计数:
LENGTH(E' a\t ')返回4(空格、a、制表符、空格),不自动trim
MySQL中别把LENGTH()当字符数用
MySQL的LENGTH()返回的是**字节数**,不是字符数。utf8mb4下,英文占1字节、中文占3–4字节、emoji可能占4字节——所以LENGTH('你好')返回6或8,取决于具体编码细节。
想按字符过滤?必须换CHAR_LENGTH()。比如限制评论最多200字符:WHERE CHAR_LENGTH(comment) > 200,而不是LENGTH(comment) > 200,否则中文用户刚输50个字就触发截断。
-
CHAR_LENGTH()和LENGTH()对ASCII字符串结果一致,但语义完全不同 - 字段类型为
TEXT或VARCHAR时,CHAR_LENGTH()更贴近业务含义 - 如果真要估算存储开销(比如判断是否接近
max_allowed_packet),才用LENGTH()
SQL Server里LEN()和DATALENGTH()的坑
SQL Server没有LENGTH()或OCTET_LENGTH(),对应的是LEN()和DATALENGTH()。关键区别:LEN()会**自动去掉末尾空格再算字符数**,DATALENGTH()返回原始字节数(含末尾空格,且对Unicode类型如nvarchar,每个字符算2字节)。
典型翻车场景:判断用户名是否为空字符串。LEN('abc ') = 3,但DATALENGTH('abc ') = 6(假设varchar);如果是nvarchar('abc '),DATALENGTH()会返回12。
- 做长度校验(如密码≥8字符)?用
LEN() - 做协议层字节对齐、或排查字段实际占用空间?用
DATALENGTH() -
LEN(NULL)返回NULL,不是0,WHERE中需补AND col IS NOT NULL
跨数据库迁移时最容易忽略的兼容点
直接把MySQL的LENGTH(col) > 100搬到PostgreSQL,逻辑就反了——MySQL是字节数,PostgreSQL是字符数。同样,把PostgreSQL的OCTET_LENGTH(col)抄到MySQL,会报错(MySQL不支持该函数)。
真正安全的做法是:明确语义优先。如果业务规则是“最多100个可见字符”,所有库都统一用CHAR_LENGTH()(PostgreSQL/MySQL都支持);如果必须按字节,MySQL用LENGTH(),PostgreSQL用OCTET_LENGTH(),SQL Server用DATALENGTH(),不能混用。
WHERE里带函数的条件基本无法走索引,哪怕加了函数索引(如CREATE INDEX idx_len ON t ((LENGTH(content)))),也只对特定表达式生效,且维护成本高。线上高频查询应尽量避免。











