LEFT 与 RIGHT 是什么
从字符串左端或右端取固定长度的子串,常用于取编号前缀、手机号后四位、年份前两位。两个函数都按字符计算,处理多字节中文是安全的,不会把一个汉字截成半个字节。
基本信息
| 语法 | LEFT(str, n) 取左侧 n 个字符,RIGHT(str, n) 取右侧 n 个字符 |
|---|---|
| 超长处理 | n 大于字符串长度时返回整个字符串,不报错 |
| 多字节 | 按字符计,中文与 emoji 都不会被切断 |
| PostgreSQL 负数 | n 为负时表示去掉另一端 |n| 个字符,与直觉相反 |
| 索引影响 | 对列使用 LEFT 或 RIGHT 过滤无法走索引 |
| 常见替代 | 前缀匹配用 LIKE 'abc%',取中间段用 SUBSTRING |
基础用法
基础用法
-- MySQL 与 PostgreSQL 都支持
SELECT LEFT(order_no, 4) AS prefix, -- 取编号前 4 位
RIGHT(phone, 4) AS phone_tail, -- 取手机号后 4 位
LEFT('你好世界', 2) AS chars -- 取 2 个汉字,不会出现半个字
FROM orders;
-- 过滤索引列时改写为前缀匹配,才能走索引
SELECT * FROM orders WHERE order_no LIKE 'A001%';PostgreSQL 的负数语义
PostgreSQL 的负数语义
-- PostgreSQL 允许负 n:相当于从另一端去掉若干字符
SELECT left('abcdef', -2); -- 'abcd':去掉右侧 2 个
SELECT right('abcdef', -2); -- 'cdef':去掉左侧 2 个
-- 语义容易看错,团队内建议只传正数,去掉字符改用其它写法取子串函数对照
| 需求 | MySQL 8 | PostgreSQL |
|---|---|---|
| 左侧 n 个字符 | LEFT(str, n) | left(str, n) |
| 右侧 n 个字符 | RIGHT(str, n) | right(str, n) |
| 任意位置起取 | SUBSTRING(str, pos, len) | substring(str from pos for len) |
| 前缀匹配 | LIKE 'abc%' | LIKE 'abc%' 或 left(str,3) |
| 按分隔符取段 | SUBSTRING_INDEX | split_part |
典型使用场景
- 取编号前缀做分类统计,例如订单号里的年份部分
- 展示手机号后四位,兼顾识别与隐私
- 取身份证前 6 位定位行政区划码
- 从版本号字符串里取主版本号
- 展示时取名称前 8 个字作为短标识
- 数据校验:判断某个字段是否以指定前缀开头
- 批量导出时截短长文本列,控制文件体积
- 按号段归类:取编号前几位映射到业务分类
LEFT 与 LIKE 'abc%' 结果等价但性能不同:前者对列做了运算,索引用不上;后者是前缀匹配,可以走 B+ 树索引。过滤条件里优先写 LIKE。
取子串前先确认长度够不够:RIGHT(phone, 4) 对空字符串返回空串、对不足 4 位的值返回原值,不会报错但展示会不整齐,必要时用 LPAD 补齐位数。
对索引列使用 LEFT 或 RIGHT 过滤(例如 WHERE LEFT(code, 4) = 'A001')会导致索引失效并全表扫描,改写成 WHERE code LIKE 'A001%' 或对应的范围条件。