首页/数据/SQL 速查/SUBSTRING 截取子串
函数速查60 条

SUBSTRING 截取子串

按位置截取子串:MySQL 支持负数位置从尾部数;PostgreSQL 用 substring(str from start for len),位置从 1 开始。

SQL 速查数据更新于 2026-10-13

SUBSTRING 是什么

SUBSTRING 按位置截取子串,是字符串清洗与编码解析的常用工具。MySQL 支持 SUBSTRING(str, pos, len),pos 为负数时从末尾往前数,另有 LEFT 与 RIGHT 做定长截取;PostgreSQL 既支持 substring(str from start for count) 这种标准写法,也支持 substr(str, start, count) 函数写法。两库的截取都按字符计数而不是字节,UTF-8 下中文不会被截成半个字符,但与按字节返回长度的函数混用时要注意口径。

基本信息

MySQL 写法SUBSTRING(str, pos) 与 SUBSTRING(str, pos, len)
MySQL 负数位置pos 为负表示从字符串末尾往前数
PostgreSQL 写法substring(str from 2 for 3) 或 substr(str, 2, 3)
定长截取LEFT(str, n) 与 RIGHT(str, n)
计数单位按字符计数,UTF-8 下中文不会被截断
索引影响对列做截取后再比较,普通索引无法用于该列

典型使用场景

  • 提取固定位编码:从订单号里截出渠道与日期段
  • 脱敏展示:手机号只显示前三位与后四位
  • 按前缀分组:用截取结果当分组维度
  • 清洗脏数据:去掉前后多余内容再入库
  • 拆分拼接字段:把用分隔符拼在一起的字段拆开
  • 长度规整:把超长文本截到目标列可以接受的长度

示例

示例
-- MySQL
SELECT SUBSTRING('ORDER202405010001', 1, 5)  AS prefix,   # ORDER
       SUBSTRING('ORDER202405010001', 6, 8)  AS day_part, # 日期段
       SUBSTRING('ORDER202405010001', -4)    AS tail,     # 末尾四位
       LEFT('ORDER202405010001', 5)          AS head;     # 定长左截

-- PostgreSQL
SELECT substring('ORDER202405010001' from 1 for 5) AS prefix,
       substr('ORDER202405010001', -4)             AS tail,
       left('ORDER202405010001', 5)                AS head;

-- 脱敏示例:只保留前三位与后四位
SELECT CONCAT(LEFT(phone, 3), '****', RIGHT(phone, 4)) FROM users;

截取写法对照

需求MySQLPostgreSQL
从第 2 位取 3 个字符SUBSTRING(s, 2, 3)substring(s from 2 for 3)
末尾四位SUBSTRING(s, -4) 或 RIGHT(s, 4)right(s, 4)
前五位LEFT(s, 5)left(s, 5)
长度CHAR_LENGTH(s)char_length(s)
字节长度LENGTH(s)octet_length(s)
MySQL 的 LENGTH 返回字节数,CHAR_LENGTH 返回字符数;中文在 UTF-8 下占三个字节,用错函数会让长度判断差好几倍。
在 WHERE 里对列使用 SUBSTRING 会让该列的普通索引失效,条件能改写为前缀比较(LIKE 'abc%')时优先用前缀形式。
位置从 1 开始计数,不是 0;从 0 开始写不会报错但结果与预期不同,迁移脚本里要特别核对。

使用要点

  • 先确认位置基准:SQL 里下标从 1 开始
  • 定长截取优先用 LEFT 与 RIGHT,意图更清楚
  • 按字符计数,避免用字节长度做长度校验
  • 截取结果参与比较时考虑加冗余列或函数索引
  • 脱敏逻辑放在接口层或视图,原表保留完整数据
  • 处理空串与 NULL:先兜底再截取,避免整列变 NULL

易错点

  • 把位置当成从 0 开始,截取结果整体偏移一位
  • 用 LENGTH 判断字符数,中文场景下长度判断明显偏大
  • WHERE 中对列做 SUBSTRING 比较,导致索引失效退化为全表扫描
  • 脱敏后的结果直接写回原表,原始数据丢失无法恢复
  • 对可能为 NULL 的列直接截取,结果整列变 NULL 却查不出原因

数据来源与参考

  • MySQL 8.0 Reference Manual · String Functions
  • PostgreSQL Documentation · String Functions and Operators
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌