LEFT和RIGHT函数分别从字符串左、右端截取指定长度字符,语法为LEFT(str,n)和RIGHT(str,n),n须为非负整数;n超出长度时返回全部字符,n为0时返回空串,常用于提取固定前缀或后缀。

LEFT 和 RIGHT 函数在 SQL 中的语义和基本用法
LEFT 和 RIGHT 是多数主流数据库(如 MySQL、SQL Server、PostgreSQL 14+、SQLite)支持的字符串截取函数,用于从字符串左侧或右侧提取指定长度的字符。它们不依赖正则或位置计算,适合提取固定长度前缀或后缀——比如订单号前3位、身份证后4位、设备码末6位等。
注意:LEFT(str, n) 等价于 SUBSTRING(str, 1, n);RIGHT(str, n) 等价于 SUBSTRING(str, LENGTH(str)-n+1, n)(但后者更啰嗦,且在不同方言中 LENGTH 可能叫 LEN 或 CHAR_LENGTH)。
常见错误现象:RIGHT(col, 5) 在某行数据实际长度不足 5 时,不会报错,而是返回全部内容(即“不够就全给”),这点容易被忽略,导致特征码长度不一致。
提取固定长度特征码时必须检查原始字段长度
直接套用 LEFT(col, 4) 或 RIGHT(col, 6) 很危险——如果 col 存的是空值、空字符串或长度小于目标值,结果会失真。例如设备编号字段 sn 本该是 12 位,但部分数据只有 8 位,RIGHT(sn, 10) 就会把整个 8 位都当“后10位”返回。
实操建议:
- 先用
SELECT sn, LENGTH(sn), LEFT(sn, 4), RIGHT(sn, 6) FROM devices LIMIT 10;快速观察真实长度分布 - 对关键字段加约束:比如在 WHERE 中补
AND LENGTH(sn) >= 12,再做截取 - 需要兜底逻辑时,用
CASE WHEN LENGTH(sn) >= 10 THEN RIGHT(sn, 10) ELSE NULL END显式控制 - MySQL 用户注意:
LENGTH()返回字节数,中文可能占多字节;要按字符数判断请用CHAR_LENGTH()
跨数据库兼容性陷阱:PostgreSQL 默认不支持 LEFT/RIGHT
PostgreSQL 在 14 版本之前完全不提供 LEFT 和 RIGHT 函数,强行使用会报错 ERROR: function left(unknown, integer) does not exist。即使升级到 14+,也需确认是否启用了 pg_catalog 中的内置函数(默认开启,但某些精简部署可能禁用)。
替代方案(兼容所有 PostgreSQL 版本):
SELECT SUBSTRING(sn FROM 1 FOR 4) AS prefix, -- 等效 LEFT(sn, 4)
SUBSTRING(sn FROM -6 FOR 6) AS suffix -- 等效 RIGHT(sn, 6),负起始位置表示从末尾算其他注意事项:
- SQL Server 的
RIGHT支持负数长度?不支持,会报错;必须确保第二个参数 ≥ 0 - SQLite 的
LEFT/RIGHT从 3.40.0 开始才有,旧版本只能靠SUBSTR模拟 - Oracle 完全没有
LEFT/RIGHT,得统一用SUBSTR(col, 1, 4)和SUBSTR(col, -6, 6)
性能影响:LEFT/RIGHT 本身几乎无开销,但隐式类型转换会拖慢查询
LEFT 和 RIGHT 是纯字符串操作,只要输入列已建索引,且你只对原列做截取(如 WHERE LEFT(order_id, 3) = 'ABC'),大多数引擎无法利用索引——因为这是前缀函数,不是前缀匹配。
真正影响性能的往往是后续误操作:
- 把
LEFT(created_at, 7)用在日期字段上:created_at是DATETIME类型,LEFT会触发隐式转字符串(格式依赖 locale 和数据库设置),既不可控又低效 - 在
ON条件里对关联字段用RIGHT:比如ON RIGHT(a.code, 5) = RIGHT(b.code, 5),会导致两表都无法走索引 - 正确做法:特征码应作为独立字段存储并加索引,而不是每次查询都现场计算
如果你正在从日志或原始表里临时抽特征码做分析,那 LEFT/RIGHT 完全够用;但要是高频查询场景,别省那点存储空间——存个 feature_code CHAR(6) 字段,写入时就计算好。

















