LEFT和RIGHT这两个函数可以说是SQL字符串处理中最基础、最常用的工具了。简单来说,LEFT就是从字符串左边开始数指定长度的字符,RIGHT则是从右边数。二者都需要一个非负整数作为截取长度——这个细节很重要,很多人在这里踩过坑。

关于这两个函数,其实有很多值得深入聊一聊的地方,不仅仅是语法层面的事情。
LEFT和RIGHT的基本用法与参数边界
LEFT和RIGHT在主流SQL方言中都能用——MySQL、SQL Server、PostgreSQL 13+(12及以下版本需要自己实现)、SQLite都支持。两个参数:string和length,其中length必须是≥0的整数。
实务中大家容易掉进去的坑,主要是负数length和NULL输入。传负数的话,多数数据库直接报错——比如MySQL会抛出Invalid argument for function LEFT;但SQL Server比较"温柔",它会默默返回空字符串,这种静默失败反而更容易掩盖逻辑问题,值得警惕。
来看几个标准示例:
LEFT('ABC123', 3)→'ABC'RIGHT('ABC123', 2)→'23'- 如果传入的length超过字符串本身长度——比如
LEFT('AB', 5)——结果就是原字符串本身,不会报错,这点和很多人的直觉不太一样
顺便提一下,PostgreSQL中如果要做类似操作,需要启用pg_trgm扩展,或者在13+版本里原生使用。对于更早的版本,可以用SUBSTRING(str FROM 1 FOR n)和SUBSTRING(str FROM LENGTH(str)-n+1)来替代。
截取前缀时如何避免NULL和长度不足的麻烦
实际业务中,编号字段往往不是那么"干净"——NULL、空字符串、长度参差不齐是常态。如果无脑写LEFT(order_no, 4),NULL输入直接返回NULL,短编号(比如'X1')也不会帮你补位成'X1__'。
那怎么处理?几个实用做法:
- 用
COALESCE(order_no, '')阻隔NULL的传导效应 - 配合
CHAR_LENGTH(COALESCE(order_no, '')) >= 4做前置校验,判断够不够截取长度——尤其在WHERE条件中使用时,这种校验特别重要 - 如果需要统一输出长度(比如所有编号都要截取成4位前缀),建议先用
LPAD或RPAD标准化,别只依赖LEFT
需要强调的是:MySQL和SQL Server对于NULL输入的行为是一致的——都返回NULL。但这不代表可以偷懒不做NULL处理,业务逻辑层面仍然需要显式防护,别把"不会报错"等同于"安全"。
用RIGHT截后缀时,方向与编码问题
很多人觉得用RIGHT提取后缀(比如订单号末3位流水号)没啥好说的,但在多字节字符集下,问题就来了——它是按字节数算还是按字符数算?
答案是字符数。MySQL 8.0+、SQL Server、PostgreSQL都是这么处理的。但要注意的是,MySQL 5.7及更早版本在某些collation下表现不稳定——比如RIGHT('订单-2024001', 3)在正确配置下返回'001',但如果配置不对,结果可能错乱。
另一个常见问题是:如果字段里混进了emoji或中文,而应用层用了latin1连接UTF8MB4的表,那RIGHT返回的结果可能错位。这不是函数本身的问题,而是传输层解码错误,查问题的时候别冤枉了函数。
一个更靠谱的建议:对于不定长后缀(比如要按分隔符'-'截取最后一段),直接用SUBSTRING_INDEX(MySQL)或SPLIT_PART(PostgreSQL)会可靠得多——RIGHT在这个场景下不是最佳选择。
LEFT + RIGHT组合使用时,性能与可读性的博弈
有些开发者会写出LEFT(RIGHT(order_no, 6), 3)这种嵌套写法来取倒数第4~6位——虽然能跑,但可读性差,执行效率也不好说,尤其是大表上不支持索引优化的时候。
几个替代思路:
- 优先用
SUBSTRING(标准SQL)或MID(MySQL)替代嵌套:SUBSTRING(order_no, LENGTH(order_no)-5, 3) - 如果这个提取逻辑在业务中高频使用,建议在表里新增生成列(Generated Column,MySQL 5.7+/PostgreSQL 12+都支持)并建索引,避免每次查询都重新计算
- SQLite不支持生成列,这时候可以用视图封装逻辑,但视图无法被索引加速,需要权衡
- 绝对不要在WHERE子句里对字段套
LEFT/RIGHT做条件过滤——比如WHERE LEFT(code, 2) = 'AB'——这会让索引失效。正确的写法是用前缀匹配:WHERE code LIKE 'AB%'
说到最后,真正需要警惕的不是函数本身,而是编号规则是否稳定。如果业务允许前缀从2位动态升到3位,那硬编码LEFT(x, 2)就是埋雷。我倾向于把长度逻辑外移到配置表或应用层,SQL只负责执行不负责决策——这样后期维护起来会轻松得多。
