SUBSTRING函数基本用法为从指定位置截取字符串,参数顺序依数据库而异:SQL标准用SUBSTRING(str FROM start FOR length),MySQL/SQL Server用SUBSTRING(str, start, length),起始位置从1计数;省略length时截取至末尾。

SUBSTRING函数的基本用法和参数顺序
SQL标准中SUBSTRING有三种常见写法:SUBSTRING(str FROM start FOR length)(PostgreSQL/SQL标准)、SUBSTRING(str, start, length)(MySQL、SQL Server)、SUBSTRING(str, start)(省略长度时截取到末尾)。参数顺序容易混淆——尤其在跨数据库迁移时,MySQL里第二个参数是起始位置(从1开始),不是0;SQL Server同理;而PostgreSQL支持两种语法但推荐用FROM/FOR关键字形式。
- 起始位置始终从1计数,不是0(这点和多数编程语言不同)
-
length为0或负数时,多数数据库返回空字符串(MySQL 8.0+、PostgreSQL),但SQL Server会报错 - 若
start超出字符串长度,结果为空字符串(不是NULL)
截取固定长度字符串的典型场景与写法
最常遇到的是:从身份证号取出生年月(第7~14位)、从订单号取日期段(第1~8位)、从日志字段提取前100字符做摘要。这时关键是把start和length写准,且注意字段是否可能为NULL。
- 如果源字段可能为NULL,直接套用
SUBSTRING(col, 1, 10)会导致整行结果为NULL(多数数据库行为),应先用COALESCE(col, '')兜底 - 截取长度超过原字符串时,不会报错,自动截到末尾(安全,但需确认业务是否接受这种“静默缩短”)
- MySQL中
SUBSTRING('abc', 5, 2)返回''(空字符串),不是NULL;但SUBSTRING(NULL, 1, 2)返回NULL
SELECT order_id, SUBSTRING(order_id, 1, 8) AS date_part, COALESCE(SUBSTRING(remark, 1, 100), '') AS remark_summary FROM orders;
不同数据库对SUBSTRING的兼容性差异
同一个语句在MySQL和PostgreSQL里可能因语法风格不兼容而失败。例如SUBSTRING(email FROM 1 FOR 3)在PostgreSQL可行,在MySQL会报错,必须写成SUBSTRING(email, 1, 3)。
- SQL Server支持
SUBSTRING和LEFT/RIGHT,但LEFT(col, 5)比SUBSTRING(col, 1, 5)更直观,且语义明确 - SQLite只支持
SUBSTR(少了个I),参数顺序同MySQL:SUBSTR(str, start, length) - Oracle用
SUBSTR,但起始位置支持负数(从末尾倒数),如SUBSTR('abcde', -3, 2)返回'cd';其他主流数据库不支持负起始位
性能与可读性提醒
SUBSTRING本身是轻量级字符串操作,但若在WHERE条件中对字段使用它(如WHERE SUBSTRING(phone, 1, 3) = '138'),会导致索引失效——除非你建了函数索引(PostgreSQL/Oracle支持,MySQL 8.0+部分支持)。
- 避免在JOIN或ORDER BY里大量使用
SUBSTRING处理长文本字段,CPU开销会上升 - 如果只是取前N位,且数据库支持,优先用
LEFT(col, N)(SQL Server、MySQL),语义更清晰,部分引擎优化更好 - 日志类场景中,用
SUBSTRING(col, 1, 2000)代替col投喂给应用层,能防止超长内容拖慢查询或触发客户端截断
真正容易被忽略的是:当字段定义为VARCHAR(10)却存了5个汉字(UTF8mb4下占15字节),SUBSTRING(col, 1, 5)截的是“字符数”,不是“字节数”——所有主流SQL引擎都按字符单位计算,这点和底层存储编码无关。










