能截取,但必须组合substring、charindex/instr或substring_index等函数定位后再截取;不同数据库语法差异大,mysql用substring_index最稳,sql server需charindex配合substring,oracle用instr配合substr,且起始位置均从1开始,空值返回null,分隔符不存在时行为各异。

直接说结论:SQL 截取字符串不是靠“猜位置”,而是靠组合函数定位 + 截取,关键在 SUBSTRING、CHARINDEX/INSTR、SUBSTRING_INDEX 这三类函数的配合用法。不同数据库语法差异大,不能照搬。
MySQL 里按分隔符截取(比如取邮箱用户名)
常见场景是解析 user@example.com 这类字符串,想拿 user 部分。别硬算长度,用 SUBSTRING_INDEX 最稳:
-
SUBSTRING_INDEX(email, '@', 1):取第一个@之前的所有内容 -
SUBSTRING_INDEX(email, '.', -1):取最后一个.之后的内容(如com) - 如果分隔符不存在(比如字段里没
@),SUBSTRING_INDEX直接返回原字符串,不会报错,但结果可能不符合预期 - 注意:第三个参数是整数,正数从左往右数,负数从右往左数;不能传变量或子查询结果作该参数
SQL Server 或 Oracle 中按关键字定位再截取
比如地址字段值为 广州市天河区体育西路89号,要截取 体育西路89号 —— 关键字 体育西路 位置不固定,得先找位置再切:
- SQL Server 用
CHARINDEX('体育西路', address)找起始位置,再套SUBSTRING(address, CHARINDEX('体育西路', address), LEN(address)) - Oracle / MySQL 用
INSTR(address, '体育西路'),逻辑一样,但索引从 1 开始,和SUBSTR兼容 - 如果关键字不存在,
CHARINDEX返回 0,SUBSTRING(..., 0, ...)会从第 1 位开始截,容易出错;建议加CASE WHEN CHARINDEX(...) > 0 THEN ... ELSE NULL END包一层 -
CHARINDEX不区分大小写,CHARINDEX('street', address)也能匹配Street
通用但易踩坑的 SUBSTRING 用法
SUBSTRING 看似简单,但参数行为跨数据库不一致:
- SQL Server 和 Oracle:起始位置从 1 开始,
SUBSTRING(str, 1, 5)取前 5 个字符 - MySQL 的
SUBSTR支持负起始位置:SUBSTR(str, -3)表示从倒数第 3 个字符开始到末尾 - 所有数据库中,长度参数(第三个参数)都不能为负;传负值通常被当作 0 或报错
- 如果起始位置超出字符串长度(比如
SUBSTRING('abc', 10, 2)),多数数据库返回空字符串,不是报错 —— 容易漏掉数据异常 - 中文字符一般按字符计数,不是按字节,但若字段是
VARBINARY类型或用了非 UTF8 排序规则,可能出偏移错位
LEFT/RIGHT 函数只适合固定边界的截取
它们快、可读性好,但仅适用于“取前 N 位”或“取后 N 位”这种明确边界的情况:
-
LEFT(order_no, 4)提取订单号前 4 位年份,前提是所有订单号格式统一(如20250001) -
RIGHT(create_time, 3)取时间字符串末尾 3 个字符(如毫秒部分),但若源字段含时区或格式不一(2025-01-01T12:00:00Zvs2025/01/01 12:00:00),结果不可靠 - 这些函数不接受表达式作为长度参数,比如
LEFT(name, LEN(name)-2)在 SQL Server 可用,在某些旧版 MySQL 会报错 - 遇到空值时,
LEFT(NULL, 5)返回NULL,不是空字符串 —— 如果业务需要空字符串兜底,得显式写ISNULL(LEFT(...), '')或COALESCE(LEFT(...), '')
最麻烦的不是函数不会用,而是同一个 SQL 在开发环境(MySQL)跑通了,上线到生产(SQL Server)就返空值 —— 因为 INSTR 和 CHARINDEX 行为不同、SUBSTRING 负索引不兼容、甚至空格处理逻辑都可能差一个 trim。写之前先确认目标数据库类型,别依赖“看起来差不多”。











