substring函数基本用法为substring(str, start, length),起始位置从1开始;mysql/postgresql/sql server语法相似但细节差异大,oracle常用substr;跨库建议优先用left/right或正则替代。

SUBSTRING函数的基本用法和参数顺序
SUBSTRING 函数在不同数据库中的参数顺序不一致,这是最容易出错的地方。MySQL 和 PostgreSQL 用 SUBSTRING(str, pos, len),SQL Server 和 Oracle 则支持 SUBSTRING(str, start, length) 和 SUBSTR(str, start, length) 两种写法,但起始位置都是从 1 开始(不是 0)。如果传入负数或超出长度的 len,MySQL 会截断到末尾,SQL Server 则可能报错或返回空字符串。
实操建议:
- 先查当前数据库的文档确认语法,比如在 SQL Server 中执行
SELECT SUBSTRING('hello', 2, 10)返回ello; - 避免硬写负数起始位,PostgreSQL 虽支持
SUBSTRING('abc', -1)表示从末尾取,但 MySQL 不认,跨库迁移时会直接报错; - 如果要兼容多种数据库,优先用
LEFT()、RIGHT()或正则(如REGEXP_SUBSTR)替代复杂截取逻辑。
处理 NULL 或超长字段时的常见错误
当字段值为 NULL 时,SUBSTRING(NULL, 1, 5) 结果仍是 NULL,不会报错但容易掩盖数据质量问题。更隐蔽的问题是字段实际长度小于指定截取长度——比如 SUBSTRING(name, 1, 10) 应用于只有 3 个字符的 name 字段,在所有主流数据库中都会安静地返回全部 3 个字符,不会补空或报错,导致后续比对或拼接逻辑出错。
实操建议:
- 用
CASE WHEN LEN(column) 显式控制边界; - 配合
ISNULL()(SQL Server)或COALESCE()(通用)提前处理空值,例如SUBSTRING(COALESCE(title, ''), 1, 20); - 在 WHERE 条件里慎用
SUBSTRING做模糊匹配,它无法利用索引,大数据量下性能极差。
从邮箱提取用户名部分的典型场景
想从 user@example.com 中提取 user,不能简单写 SUBSTRING(email, 1, 4)——因为用户名长度不固定。正确做法是结合 CHARINDEX(SQL Server)、LOCATE(MySQL)或 POSITION(PostgreSQL)定位 @ 的位置。
以 SQL Server 为例:
SELECT
SUBSTRING(email, 1, CHARINDEX('@', email) - 1) AS username
FROM users
WHERE email IS NOT NULL AND CHARINDEX('@', email) > 0;
注意点:
-
CHARINDEX('@', email) - 1可能为 0(比如邮箱以 @ 开头),此时SUBSTRING返回空字符串,需加条件过滤; - MySQL 要用
LOCATE('@', email),且它在找不到时返回 0,行为一致; - 如果邮箱含多个 @(虽然非法),
LOCATE只返回第一个,CHARINDEX同理,无需额外处理。
用 SUBSTRING 实现动态截断并保留后缀
比如日志字段太长,只想显示前 50 字 + “…”(但只在超长时加),不能直接拼接,否则短文本也会多出省略号。关键在于判断长度后再决定是否截断。
通用写法(SQL Server / PostgreSQL):
SELECT
CASE
WHEN LEN(content) > 50
THEN SUBSTRING(content, 1, 47) + '...'
ELSE content
END AS preview
FROM logs;
这里 47 是因为 ‘...’ 占 3 位,确保总长 ≤ 50。容易被忽略的是:不同数据库对中文字符的长度计算方式不同——SQL Server 的 LEN() 按字符数算,而某些 collation 下 DATALENGTH() 按字节数算,如果字段是 NVARCHAR 存中文,LEN() 更可靠。











