LEFT函数从字符串左侧截取指定非负整数长度的字符,RIGHT函数从右侧截取,二者均要求length≥0,超长时返回原字符串,NULL输入返回NULL,实际使用需配合COALESCE和长度校验防异常。
LEFT 和 RIGHT 是多数主流 SQL 方言(如 MySQL、SQL Server、PostgreSQL 13+、SQLite)支持的字符串截取函数,用于从字符串左侧或右侧提取指定长度的字符。它们接受两个参数:string 和 length,其中 length 必须是非负整数。
常见错误是传入负数或 NULL —— 多数数据库会直接报错(如 MySQL 报 Invalid argument for function LEFT),少数(如 SQL Server)可能返回空字符串但不提示,容易掩盖逻辑问题。
LEFT('ABC123', 3) → 'ABC'
RIGHT('ABC123', 2) → '23'
length 超过原字符串长度(如 LEFT('AB', 5)),结果就是原字符串本身,不会报错pg_trgm 扩展或改用 SUBSTRING(str FROM 1 FOR n) / SUBSTRING(str FROM LENGTH(str)-n+1)
实际业务中编号字段(如 order_no)常存在 NULL、空字符串或长度不一的情况,直接套用 LEFT(order_no, 4) 可能返回 NULL(当输入为 NULL 时),或意外截断短编号(如 'X1' 被截成 'X1',而非预期的 'X1__' 占位)。
COALESCE(order_no, '') 防止 NULL 传导到 LEFT
CHAR_LENGTH(COALESCE(order_no, '')) >= 4 做前置校验,再决定是否截取(尤其在 WHERE 条件中)LPAD 或 RPAD 标准化,而不是依赖 LEFT
LEFT(NULL, 4) 直接返回 NULL;而 SQL Server 对 NULL 输入也返回 NULL,这点行为一致,但不可当作“安全”——业务逻辑仍需显式处理用 RIGHT 提取后缀(如订单号末 3 位流水号)看似简单,但在多字节字符集(如 UTF8MB4)下,RIGHT 按“字节数”还是“字符数”计算?答案是:按字符数(不是字节)。这点在 MySQL 8.0+、SQL Server、PostgreSQL 中均如此,但老版本 MySQL(5.7 及之前)在某些 collation 下可能表现不稳定。
RIGHT('订单-2024001', 3) 在正确配置下返回 '001',不是乱码或截半字符RIGHT 返回结果可能错位 —— 这不是函数问题,而是传输层解码错误RIGHT 处理不定长后缀(如按分隔符 '-' 截取最后一段),此时应改用 SUBSTRING_INDEX(MySQL)或 SPLIT_PART(PostgreSQL)更可靠有人会写 LEFT(RIGHT(order_no, 6), 3) 来取倒数第 4~6 位,这种嵌套虽可行,但可读性差、执行效率未必优(尤其在大表上无索引支持时),且不同数据库优化器对嵌套函数的支持程度不一。
SUBSTRING(标准 SQL)或 MID(MySQL)替代嵌套:SUBSTRING(order_no, LENGTH(order_no)-5, 3)
LEFT/RIGHT 做条件过滤(如 WHERE LEFT(code, 2) = 'AB'),这会让索引失效;应改用前缀匹配:WHERE code LIKE 'AB%'
真正麻烦的不是函数本身,而是编号规则是否稳定——如果业务允许前缀动态变长(比如从 2 位升到 3 位),硬编码 LEFT(x, 2) 就成了埋点。这时候得把长度逻辑外移到配置表或应用层,SQL 只负责执行。