substr(或substring)是sql中提取中间字符的首选函数,专为“从指定位置截取指定长度”设计;left+right嵌套逻辑复杂、易错、可读性差且容错性低。

SQL里取中间字符,SUBSTR 是首选,不是 LEFT + RIGHT 套娃
直接说结论:SUBSTR(或 SUBSTRING,取决于数据库)才是专为“从指定位置截取指定长度”设计的函数;用 LEFT 和 RIGHT 拼凑中间段,逻辑绕、易错、可读性差,还可能在空值或长度不足时崩掉。
比如想从 '2024-05-17_order_abc123' 中提取下划线之间的 'order',硬套 LEFT(RIGHT(...)) 得算两次位置、两次长度,稍一偏差就切歪。
-
SUBSTR(str, start_pos, length):MySQL / PostgreSQL / Oracle 都支持这三参数形式,开箱即用 - SQLite 用
SUBSTR(str, start_pos, length),但起始位置从 1 开始(不是 0) - SQL Server 用
SUBSTRING(str, start_pos, length),同样从 1 开始 - 如果只给两个参数(如
SUBSTR(str, start_pos)),多数数据库会截到末尾——但别依赖这个,显式写length更稳
遇到动态位置(比如两次下划线之间),先用 INSTR 或 CHARINDEX 定位
固定位置好办,但真实场景里分隔符位置往往不固定。这时候不能手写数字,得靠定位函数算起始点和长度。
例如提取 'user@example.com' 中 @ 和 . 之间的 'example':
SELECT SUBSTR(email,
INSTR(email, '@') + 1,
INSTR(email, '.') - INSTR(email, '@') - 1)
FROM users;
注意几个坑:
-
INSTR在 MySQL/Oracle/SQLite 中可用;SQL Server 得换CHARINDEX('@', email) - 如果
email里没有 @ 或 .,INSTR返回 0,后续计算会得出负长度或越界——必须加CASE WHEN判断,或用NULLIF拦住 - 别忘了 +1 / -1 这类偏移:@ 后一位才是起点,. 前一位才是终点
LEFT 和 RIGHT 不适合取中间段,但可以辅助清理边界
它们真有用的地方是切头去尾,比如去掉前缀或后缀,而不是夹中间。强行用来取中段,代码像解方程:
-- 别这么写(难懂、难维护)
SELECT LEFT(RIGHT('abc123def', 6), 3); -- 得到 '123'?但长度一变就废
更现实的用法是预处理:
- 用
LEFT(full_path, LENGTH(full_path) - 4)去掉文件扩展名(假设都是 .txt) - 用
RIGHT(filename, 3)快速判断后缀,再决定是否进复杂截取逻辑 - 组合时优先考虑
REPLACE或正则(如 PostgreSQL 的REGEXP_REPLACE),比嵌套LEFT/RIGHT清晰得多
跨数据库兼容性差,别默认 SUBSTR 行得通
看着名字一样,但行为细节常踩坑:
- PostgreSQL 支持负数
start_pos(从末尾倒数),MySQL 不支持——写SUBSTR(str, -3, 2)在 MySQL 里直接报错 - SQL Server 的
SUBSTRING对超长length自动截断,MySQL 的SUBSTR则按实际剩余字符返回,行为一致但文档没明说,别赌 - Oracle 的
SUBSTR第二个参数允许负数,含义是“从右往左数第 N 位开始”,和 PostgreSQL 不同 - 如果项目要兼容多库,建议封装成视图或应用层处理,别在 SQL 里写太花的字符串逻辑
最麻烦的不是函数名,而是空值传播:一个 NULL 字段进 SUBSTR,整列变 NULL,连 COALESCE 都得提前包一层——这点容易被忽略,查半天才发现是源头数据没兜住。










