substring函数用于截取字符串,起始位置从1开始;语法为substring(string, start, length),支持多数数据库但越界和空值处理存在差异。

SQL里SUBSTRING函数怎么用,起始位置从1开始
SUBSTRING 是多数数据库(MySQL、PostgreSQL、SQL Server、Oracle)都支持的截取函数,但注意:它的起始位置是 1,不是编程语言里常见的 0。写成 SUBSTRING(col, 0, 5) 在 MySQL 中会返回空,在 SQL Server 中则可能报错或行为异常。
常见写法:
-
SUBSTRING(name, 1, 3):取前3个字符(等价于LEFT(name, 3)) -
SUBSTRING(phone, 4, 8):从第4位开始,截8位(比如去掉区号) -
SUBSTRING(email, CHARINDEX('@', email) + 1, LEN(email))(SQL Server):取 @ 后域名部分;注意CHARINDEX和LEN都要配对使用
LEFT和RIGHT函数更简洁,但只适用于取头尾固定长度
如果只是取字符串开头或结尾的若干字符,LEFT 和 RIGHT 比 SUBSTRING 更直观、少出错,且在所有支持它们的数据库中语义一致。
典型场景:
-
LEFT(order_no, 6):订单号前6位做批次标识 -
RIGHT(file_path, 3):快速判断文件扩展名(但注意不严谨,建议配合CHARINDEX或正则) - MySQL 8.0+、PostgreSQL 不原生支持
LEFT/RIGHT,得用SUBSTRING(col, 1, n)或SUBSTRING(col, -n)(PostgreSQL 支持负数长度表示从末尾算)
不同数据库对空值和越界截取的处理差异大
同一个 SUBSTRING(col, 10, 5) 在字段只有3个字符时,各库表现不一:
- MySQL:返回空字符串(不报错)
- PostgreSQL:返回实际存在的子串(即空字符串或少于5位),安全
- SQL Server:若起始位置超出长度,返回
NULL;若长度为负,直接报错 - Oracle:
SUBSTR(col, 10, 5)越界时返回空,但起始位置为负数时会从末尾倒数(如-1表示最后1位)
所以别依赖“自动截断”,尤其做关联或条件判断时,建议先用 LEN/LENGTH 判断长度,或加 ISNULL/COALESCE 包裹。
想按分隔符截取?别硬套SUBSTRING,优先考虑数据库原生拆分函数
用 SUBSTRING 配合 CHARINDEX 或 INSTR 手动找分隔符位置,代码冗长还易错。例如取邮箱用户名:
SELECT SUBSTRING(email, 1, CHARINDEX('@', email) - 1) FROM users
问题在于:如果 email 不含 @,CHARINDEX 返回 0,导致 SUBSTRING(..., 1, -1) 报错(SQL Server)或返回空(MySQL)。
更稳妥的方式:
- SQL Server 2016+:直接用
STRING_SPLIT+PIVOT或子查询 - MySQL 8.0+:用
REGEXP_SUBSTR(email, '^[^@]+') - PostgreSQL:用
SPLIT_PART(email, '@', 1) - 通用兜底:加
CASE WHEN email LIKE '%@%' THEN ... ELSE email END
真正难的不是截取动作本身,而是边界情况是否被覆盖——比如空值、无分隔符、嵌套分隔符、编码导致的字节偏移错位。这些往往在测试数据里不显眼,上线后才暴露。










