PostgreSQL的SUBSTRING函数参数顺序为SUBSTRING(string FROM start FOR length),不支持MySQL式三参数写法;按字符计数,兼容UTF-8中文与emoji;推荐LEFT/RIGHT/SPLIT_PART替代简单场景。

SUBSTRING 函数的基本用法和参数顺序
PostgreSQL 的 SUBSTRING 有三种常用形式,最容易出错的是参数顺序不一致:按位置截取时是 SUBSTRING(string FROM start FOR length),不是 SUBSTRING(string, start, length)(那是 MySQL/SQL Server 风格)。省略 FOR length 时,会从起始位置一直截到末尾。
常见错误现象:SUBSTRING(name, 1, 5) 直接报错 “function substring(unknown, integer, integer) does not exist”,因为 PostgreSQL 不支持三参数数字索引写法。
- 正确写法:
SUBSTRING(name FROM 1 FOR 5) - 从第 3 字符开始取 4 个字符:
SUBSTRING(name FROM 3 FOR 4) - 兼容 SQL 标准的括号写法也可用:
SUBSTRING(name, 3, 4)—— 这个是 PostgreSQL 特有的重载,但仅限于三个参数都为标量表达式时;若含列引用或函数,优先用FROM/FOR形式更稳妥
处理中文、emoji 等多字节字符时的长度陷阱
SUBSTRING 默认按“字符”(character)计数,不是字节。这对 UTF-8 编码的中文、emoji 完全友好——SUBSTRING('你好?', FROM 1 FOR 3) 返回 '你好?',而非乱码或截断。但前提是数据库编码确实是 UTF8(绝大多数现代部署都是),且客户端连接未误设 client_encoding。
容易踩的坑:
- 在
bytea或TEXT字段里存了非 UTF-8 编码的二进制数据,再用SUBSTRING截取,结果不可预测 - 用
LENGTH()和SUBSTRING混用时注意:两者都按字符计数,所以SUBSTRING(str FROM LENGTH(str)-2 FOR 3)是安全的;但若误用OCTET_LENGTH()(按字节)来算起始位置,就会偏移错位 - 正则变体
SUBSTRING(str FROM 'pattern')对 Unicode 支持良好,但模式中.默认不匹配换行符,需加s修饰符才跨行
在 UPDATE 或 WHERE 中安全使用 SUBSTRING
直接在 UPDATE 里用 SUBSTRING 修改字段值没问题,但要注意它不改变原字段长度或类型,只返回新字符串。真正要小心的是 WHERE 条件中对大字段反复调用 SUBSTRING 可能拖慢查询——尤其没索引时。
实操建议:
- 如果经常按前缀查询(如
SUBSTRING(code FROM 1 FOR 3) = 'ABC'),建函数索引:CREATE INDEX idx_code_prefix ON tbl ((SUBSTRING(code FROM 1 FOR 3))) - 避免在
WHERE中写SUBSTRING(description FROM position('error' in description) FOR 20)这类依赖嵌套函数的表达式,先用 CTE 或子查询提取位置更清晰 -
SUBSTRING返回NULL当输入为NULL,或起始位置超出范围(如SUBSTRING('abc' FROM 10)),这点和LEFT()不同,后者对越界会静默返回全长
替代方案:LEFT / RIGHT / SPLIT_PART 的适用场景
虽然 SUBSTRING 最通用,但简单需求用专用函数更直观、性能略优,且不易写错参数。
对比说明:
- 取前 N 个字符:
LEFT(name, 5)比SUBSTRING(name FROM 1 FOR 5)少打字、易读,且不依赖 SQL 标准语法 - 取后 N 个字符:
RIGHT(name, 3)是最简写法;用SUBSTRING得写SUBSTRING(name FROM LENGTH(name)-2),易错算偏移 - 按分隔符切字段(如取邮箱用户名):
SPLIT_PART(email, '@', 1)比正则SUBSTRING(email FROM '^[^@]+')更快更稳 - 所有这些函数都遵循相同字符语义,无需额外处理 Unicode
真正需要 SUBSTRING 的地方,通常是动态起始位置(比如结合 POSITION 或正则)、或必须兼容标准 SQL 的场景。其他时候,先想清楚是不是 LEFT 就够了。

















