LEFT和RIGHT函数仅按字符数截取,n须为非负整数:n=0返回空串,n超长返回原串,n为负在MySQL报错、SQL Server返回NULL;遇NULL结果为NULL;PostgreSQL不支持需用SUBSTRING替代;字段长度不一或含多字节字符时易失真。

LEFT 和 RIGHT 不是万能切片刀,用错参数或忽略数据质量,结果就不可信。
LEFT(str, n) 和 RIGHT(str, n) 的行为边界在哪里?
这两个函数只认「字符数」,不认字节、不认位置、不自动补位。n 必须是非负整数:LEFT('abc', 0) 返回空串,LEFT('a', 5) 返回 'a'(不够就全给),LEFT(col, -1) 在 MySQL 中直接报错,在 SQL Server 中返回 NULL。
常见错误现象:
-
RIGHT(sn, 6)对长度为 4 的设备码返回全部 4 位,而非报错或补空格 - 字段含
NULL时,整个表达式结果为NULL,不是空字符串 - 在 PostgreSQL 中直接写
LEFT()会报ERROR: function left(unknown, integer) does not exist
提取固定长度特征码时,为什么不能直接套用 LEFT/RIGHT?
因为原始字段长度不一致——空值、空字符串、截断数据、用户输入随意,都会让 LEFT(col, 4) 失去“固定长度”的意义。
实操建议:
- 先探查:运行
SELECT col, LENGTH(col), LEFT(col, 4), RIGHT(col, 6) FROM t LIMIT 20;看真实分布 - 加长度守门:在 WHERE 中补
AND LENGTH(col) >= 8,再做截取 - 兜底写法:
CASE WHEN LENGTH(col) >= 6 THEN RIGHT(col, 6) ELSE NULL END,避免脏数据污染下游
MySQL 和 PostgreSQL 的 LEFT/RIGHT 兼容性差异
MySQL 原生支持 LEFT() 和 RIGHT();PostgreSQL 完全不识别这两个函数名,必须改用 SUBSTRING() 模拟。
等价写法:
- MySQL
LEFT(str, 3)→ PostgreSQLSUBSTRING(str FROM 1 FOR 3) - MySQL
RIGHT(str, 4)→ PostgreSQLSUBSTRING(str FROM LENGTH(str) - 3)(注意起始位置是字符索引,不是偏移) - 若字段可能为
NULL,PostgreSQL 还得包一层COALESCE(str, ''),否则LENGTH(NULL)返回NULL,导致整个 SUBSTRING 失效
按字节截取的需求,为什么坚决别碰 LEFT/RIGHT?
它们天生按 Unicode 字符计数,遇到 emoji 或中文时,一个字符占多个字节,但函数完全不感知。比如 LEFT('??ABC', 4) 在 MySQL 中返回 '??A'(4 个字符),但实际字节数可能是 16+;如果下游协议要求严格 10 字节,这就彻底错位。
真要按字节切:
- MySQL:改用
SUBSTR(col, 1, 10)+ 强制转latin1编码(风险极高,会丢信息) - PostgreSQL:必须先把字段转成
BYTEA,再用substring(col::bytea, 1, 10) - 更稳妥做法:把截取逻辑提到应用层,用 Python 的
bytes[:10]或 Go 的[]byte(s)[:10]显式控制字节边界
字段长度不一致、数据库方言差异、字符 vs 字节混淆——这三个点漏掉任何一个,LEFT 和 RIGHT 就从便利工具变成数据陷阱。

















