绝大多数主流数据库支持substring,mysql和oracle默认支持substr,sql server仅支持substring,postgresql两者皆可;起始位置从1开始,负数索引在mysql/oracle中支持(从末尾倒数),sql server不支持且where中使用会失效索引。

SQL里SUBSTRING和SUBSTR到底能不能混用
大多数数据库里SUBSTRING是标准函数名,SUBSTR是它的别名或简写形式,但不是所有系统都支持两者——比如SQL Server只认SUBSTRING,PostgreSQL两者都行,MySQL则更倾向SUBSTR(虽然SUBSTRING也兼容)。实际写法前先查文档,比硬记更可靠。
常见错误现象:FUNCTION 'SUBSTR' does not exist(SQL Server报错)、或column "substr" does not exist(误当字段名用了)。
截取字符串的三个参数怎么填才不越界
标准语法是SUBSTRING(str, start, length),其中start从1开始计数(不是0),length可选;省略length时截到末尾。容易踩的坑是传入负数或0作为start:MySQL允许start为负(从末尾倒数),但SQL Server直接报错;PostgreSQL对负start会返回空字符串。
-
SUBSTRING('hello world', 1, 5)→'hello' -
SUBSTRING('hello world', 7)→'world' -
SUBSTRING('hello world', -5)→ 在MySQL中是'world',在SQL Server中报错
想按分隔符截取(比如取邮箱@前面的部分)怎么办
没有内置“按字符分割后取第N段”的函数,得组合使用POSITION(或INSTR)、LENGTH和SUBSTRING。关键是算准起始位置和长度:
- PostgreSQL/Standard SQL:
SUBSTRING(email FROM 1 FOR POSITION('@' IN email) - 1) - MySQL:
SUBSTRING_INDEX(email, '@', 1)(更简洁,但非标准SQL) - SQL Server:
LEFT(email, CHARINDEX('@', email) - 1)
注意POSITION或CHARINDEX找不到分隔符时返回0,减1就变-1,可能触发错误或意外结果,生产环境建议加CASE WHEN判断。
性能影响:在WHERE里用SUBSTRING会导致索引失效吗
会。只要字段被包裹在SUBSTRING里(比如WHERE SUBSTRING(name, 1, 3) = 'abc'),绝大多数数据库无法走索引,只能全表扫描。优化思路有两个:
- 把条件改写成前缀匹配:
WHERE name LIKE 'abc%'(能用上B-tree索引) - 建函数索引(PostgreSQL/Oracle支持):
CREATE INDEX idx_name_prefix ON users (SUBSTRING(name, 1, 3)) - MySQL 8.0+ 可用生成列 + 普通索引替代
真正要截取再比较的场景不多,多数时候是设计阶段没想清楚业务需求,后期补函数反而掩盖了模型问题。










