
MySQL 字符串截取函数选哪个?LEFT()、RIGHT()、SUBSTRING() 用法和区别
三个函数都能截字符串,但适用场景不同:如果只从开头或结尾固定长度取值,LEFT() 和 RIGHT() 更直观;需要按位置或配合查找动态切分(比如取域名、截掉后缀),必须用 SUBSTRING()(或别名 SUBSTR())。
它们都支持多字节字符(如中文),但注意:参数里的“长度”单位是字符数,不是字节数。例如 LEFT('你好abc', 4) 返回 '你好ab',不是按 UTF-8 字节算。
-
LEFT(str, len):从左边取len个字符,len为负数会返回空字符串 -
RIGHT(str, len):从右边取len个字符,len为负数同样返回空字符串 -
SUBSTRING(str, pos):从第pos个字符开始取到末尾(pos从 1 开始计数) -
SUBSTRING(str, pos, len):从pos开始取len个字符;pos为负数时,从末尾倒数(-1是最后一个字符)
为什么 SUBSTRING() 的起始位置从 1 开始,不是 0?
这是 MySQL 的设计约定,和大多数 SQL 标准一致(比如 PostgreSQL 的 SUBSTR() 也从 1 开始)。如果你习惯编程语言的 0 起始(如 Python、JavaScript),这里容易错位——写成 SUBSTRING(col, 0, 5) 不报错,但会返回空字符串,因为位置 0 在 MySQL 中不合法(等效于从开头偏移 0 字符,但实际解释为无效位置)。
常见错误现象:SUBSTRING('abcde', 0, 3) → '';SUBSTRING('abcde', 1, 3) → 'abc';SUBSTRING('abcde', -2, 2) → 'de'。
- 用
LOCATE()或POSITION()找位置时,结果也是从 1 开始,可直接喂给SUBSTRING() - 想兼容其他语言逻辑?别硬改起始值,加一层
+1或用IF(pos = 0, 1, pos)处理边界更稳妥
截取邮箱用户名部分:用 SUBSTRING_INDEX() 比 SUBSTRING() 更安全
如果目标是提取 user@example.com 中的 user,别急着套 SUBSTRING() + LOCATE()。MySQL 提供了更专一的 SUBSTRING_INDEX(str, delim, count),语义清晰、不易出错。
示例:SUBSTRING_INDEX('user@example.com', '@', 1) 直接返回 'user';SUBSTRING_INDEX('a.b.c.d', '.', -2) 返回 'c.d'(负数表示从右往左数)。
- 比手写
LOCATE('@', email) - 1少一步计算,也避免email不含@时LOCATE()返回 0 导致SUBSTRING(email, 1, -1)出错 -
SUBSTRING_INDEX()对不存在的分隔符会原样返回整个字符串,行为可预测 - 它不支持正则,所以遇到复杂分隔(如多个连续点、混合符号)还得回退到
SUBSTRING()+ 正则函数(MySQL 8.0+ 的REGEXP_SUBSTR())
性能和兼容性要注意什么?
这三个函数本身开销极小,但若在 WHERE 条件里对字段做截取(比如 WHERE LEFT(name, 3) = '张'),会导致索引失效——MySQL 无法用前缀索引加速这种表达式。
真实使用中,优先考虑是否能改写成范围查询或增加生成列(Generated Column)并建索引。例如把用户名前缀存为单独字段,而不是每次查时计算。
-
SUBSTRING()在 MySQL 5.7 和 8.0 行为一致;SUBSTRING_INDEX()自 4.0 起就存在,兼容性最好 - 如果字段是
TEXT类型且内容超长,LEFT()/RIGHT()仍能正常工作,但注意临时表或排序时可能触发磁盘临时表 - 函数嵌套过深(比如五层
SUBSTRING(SUBSTRING(...)))可读性差,也难调试——拆成子查询或用 CTE(MySQL 8.0+)会更清楚
最常被忽略的是:所有这些函数对 NULL 输入都返回 NULL,而不是空字符串。如果字段可能为空,记得用 IFNULL() 或 COALESCE() 包一层,否则条件判断或连接操作容易意外中断。










