substring函数基本用法是substring(str, start, length),起始位置从1开始;mysql/postgresql采用该语法,sql server/oracle虽支持substring也兼容substr,但参数顺序与越界处理行为存在差异,需按数据库类型适配。

SUBSTRING 函数的基本用法和参数顺序
SUBSTRING 在不同数据库里参数顺序不一致,这是最容易出错的地方。MySQL 和 PostgreSQL 用 SUBSTRING(str, start, length),SQL Server 和 Oracle 则支持两种形式:SUBSTRING(str, start, length) 和 SUBSTR(str, start, length),但起始位置都是从 1 开始(不是 0)。
比如想从 'HelloWorld' 中取 'World',得写成:SUBSTRING('HelloWorld', 6, 5)。如果误写成 SUBSTRING('HelloWorld', 5, 5),就会得到 'oWorl' —— 因为第 5 位是 'o',不是 'W'。
处理超出长度的 length 参数时的行为
当指定的 length 超过剩余字符数,多数数据库会自动截断到字符串末尾,不会报错,但结果可能不符合预期。
- MySQL:
SUBSTRING('abc', 2, 10)→'bc'(安全,返回全部剩余) - PostgreSQL:同上,行为一致
- SQL Server:同样容忍,但若
start超出长度(如SUBSTRING('abc', 10, 1)),会返回空字符串'',而不是 NULL
所以别依赖“超长就报错”来兜底,显式判断长度更可靠:IF(LENGTH(str) >= start + length - 1, SUBSTRING(str, start, length), '')(MySQL 语法)。
从右端截取或定位截取时的常见替代方案
想从右边取后 3 位?别硬算起始位置,直接用 RIGHT()(SQL Server、MySQL 8.0+)或 SUBSTRING(str, LENGTH(str) - 2, 3)(兼容性更好)。但注意 LENGTH() 在 MySQL 中不计数 UTF-8 多字节字符,中文要用 CHAR_LENGTH()。
想截取某个分隔符之后的内容(例如取邮箱 @ 后的域名),单靠 SUBSTRING 不够,得配合 LOCATE() 或 CHARINDEX():
-- MySQL
SUBSTRING(email, LOCATE('@', email) + 1)
-- SQL Server
SUBSTRING(email, CHARINDEX('@', email) + 1, LEN(email))
漏掉 +1 就会把 @ 一起带上,这是高频失误点。
NULL 输入和空字符串的边界情况
SUBSTRING(NULL, 1, 1) 结果一定是 NULL,不会变成空字符串;而 SUBSTRING('', 1, 1) 在大多数系统中返回空字符串 ''。如果业务逻辑里需要统一空值处理,得提前用 COALESCE(col, '') 或 ISNULL(col, '') 包一层。
另外,某些旧版驱动或 ORM(比如早期 JDBC 连接 SQL Server)在列定义为 TEXT 类型时,对 SUBSTRING 返回类型推断异常,建议显式转成 VARCHAR:SUBSTRING(CAST(large_col AS VARCHAR(4000)), 1, 100)。
字符集、排序规则、函数大小写敏感性这些细节,在跨库迁移或联合查询时才突然暴露,平时写单表语句容易忽略。











