left和right函数在mysql、sql server、sqlite中原生支持,postgresql需安装pg_trgm扩展或改用substring;均不接受负长度,null输入返回null,超长则返回原串。

LEFT 和 RIGHT 函数在不同数据库里的可用性差异
MySQL、PostgreSQL(需安装 pg_trgm 扩展或用 substring())、SQL Server、SQLite 都原生支持 LEFT() 和 RIGHT(),但 PostgreSQL 默认不提供——直接执行会报错 function left(unknown, integer) does not exist。如果你在 pg 中看到这个错误,别急着改逻辑,先确认是否漏装扩展,或者改用标准 SQL 写法。
实操建议:
- MySQL / SQL Server / SQLite:放心用
LEFT(col, 3)或RIGHT(col, 4) - PostgreSQL:用
LEFT(col, n)前需执行CREATE EXTENSION IF NOT EXISTS "pg_trgm";更稳妥的跨库写法是SUBSTRING(col, 1, n)(前缀)和SUBSTRING(col, LENGTH(col) - n + 1)(后缀) - 注意:所有实现中,
n为负数时行为不一致——MySQL 返回空字符串,SQL Server 报错,PostgreSQL(带扩展)也报错,统一避免传负值
LEFT 截取前缀时容易忽略的 NULL 和长度越界问题
LEFT() 遇到 NULL 输入直接返回 NULL,不是空字符串;而且当指定长度超过字段实际长度时,多数数据库(MySQL/SQL Server)会静默返回整个字符串,不会截断出错——这看起来友好,但可能掩盖数据清洗疏漏。
实操建议:
- 做前缀匹配前,先用
COALESCE(col, '')或ISNULL(col, '')(SQL Server)兜底,避免整行因 NULL 被过滤掉 - 若业务要求“严格取前 5 位,不足则补空格”,得显式处理:
RPAD(LEFT(col, 5), 5, ' ') - 检查长度是否足够?可加条件:
WHERE LENGTH(col) >= 3,否则LEFT(col, 3)虽不报错,但语义已偏离预期
RIGHT 截取后缀的真实使用场景与陷阱
比前缀更常遇到的问题是“取文件扩展名”“取手机号末四位”“取日期字符串的年份”——这些看似简单,但依赖字符串长度稳定。一旦源数据格式混乱(比如有的带空格、有的含分隔符),RIGHT(col, 4) 就会失准。
实操建议:
- 取扩展名别只靠
RIGHT(filename, 3):用SUBSTRING_INDEX(filename, '.', -1)(MySQL)或SPLIT_PART(filename, '.', array_length(string_to_array(filename, '.'), 1))(PostgreSQL)更可靠 - 取手机号末四位,先
REPLACE(REPLACE(col, '-', ''), ' ', '')清理非数字字符,再RIGHT(..., 4) -
RIGHT()对多字节字符(如中文、emoji)通常按字符计数,不是字节——但 SQLite 的旧版本有例外,测试时用含中文的样本验证一下
性能影响:LEFT/RIGHT 在 WHERE 和 ORDER BY 中能走索引吗?
不能。只要函数作用于列(如 WHERE LEFT(name, 2) = '张'),就无法利用 name 字段上的 B-tree 索引,MySQL 和 PostgreSQL 都会全表扫描。这是线上慢查询的常见源头。
实操建议:
- 高频前缀查询,建生成列+索引(MySQL 5.7+):
ALTER TABLE t ADD prefix CHAR(2) GENERATED ALWAYS AS (LEFT(name, 2)) STORED, ADD INDEX idx_prefix (prefix) - 等值匹配前缀,优先用
LIKE '张%'——它能走索引,且语义相同 -
RIGHT(col, n)几乎无法优化,涉及后缀查询时,考虑反向存储(如存REVERSE(phone))并建索引,查时也用REVERSE('1234')
LEFT 和 RIGHT 表面简单,但跨库兼容性、NULL 处理、索引失效这三点,几乎每次用都会撞上一次。尤其是把它们写进 WHERE 条件还觉得“只是取几个字符而已”的时候,最危险。










