优先用LEFT截取前N字符,MySQL/SQL Server/PostgreSQL 14+原生支持;Oracle和SQLite不支持LEFT,须用SUBSTRING/SUBSTR替代,且起始位置均为1,超长时返回原串,NULL输入结果恒为NULL。

用 SUBSTRING 还是 LEFT?看数据库类型
MySQL、PostgreSQL、SQL Server 都支持 LEFT(),但 Oracle 和 SQLite 不支持——直接报错 ORA-00904: "LEFT": invalid identifier 或 no such function: LEFT。这时候必须切到 SUBSTRING()(或别名 SUBSTR())。注意:PostgreSQL 中 SUBSTRING(str FROM 1 FOR n) 和 SUBSTRING(str, 1, n) 都行;Oracle 只认 SUBSTR(str, 1, n);SQL Server 两种写法都支持,但推荐用逗号分隔形式,更稳定。
SUBSTRING 的起始位置到底是 0 还是 1?
绝大多数主流数据库(MySQL、PostgreSQL、SQL Server、Oracle)的 SUBSTRING / SUBSTR 起始位置是 1,不是编程语言里常见的 0。比如想取前 3 个字符:SUBSTRING(name, 1, 3) 是对的,SUBSTRING(name, 0, 3) 在 MySQL 里会返回空,在 PostgreSQL 里会报错 ERROR: substring() start argument must not be zero。SQLite 是个例外:它接受 0 并等价于 1,但不建议依赖这个行为——跨库迁移时容易出问题。
截取长度超过原字符串怎么办?不会报错,但结果可能和预期不一致
所有主流数据库对超长截取都做静默处理,不会报错,但返回值不同:
- MySQL / PostgreSQL / SQL Server:返回完整字符串(即自动截断到末尾)
- Oracle:
SUBSTR(str, 1, 100)对一个 5 字符的字段,仍返回这 5 个字符 - 但要注意 NULL 安全性:如果源字段为
NULL,整个表达式结果就是NULL,不会抛异常——这点常被忽略,导致前端显示空白却查不出原因 - 若需兜底,可加
COALESCE(SUBSTRING(col, 1, 5), '')或ISNULL(SUBSTRING(col, 1, 5), '')(SQL Server)
WHERE 条件里用字符串截取要小心索引失效
在 WHERE 子句中对字段做截取(如 WHERE SUBSTRING(phone, 1, 3) = '138')几乎必然导致全表扫描——因为数据库无法利用 phone 字段上的 B-tree 索引。可行替代方案:
- 用前缀匹配:
WHERE phone LIKE '138%'(能走索引) - 建计算列 + 索引(SQL Server / MySQL 5.7+):
ALTER TABLE users ADD phone_prefix AS LEFT(phone, 3) PERSISTED,再给该列建索引 - 如果必须用截取且高频查询,考虑冗余一个前缀字段,写入时同步维护
真正难处理的是那种“截中间几位”的场景,比如身份证第 7–10 位代表出生年份——这种基本没法走索引,得靠业务层缓存或预计算。










