最简通用写法是用[0-9]匹配数字并替换为空字符串:MySQL用REGEXP_REPLACE(str, '[0-9]', ''),PostgreSQL需加'g'标志,Oracle默认全局,BigQuery需r'[0-9]'前缀。

REGEXP_REPLACE 删除字符串中数字的通用写法
MySQL 8.0+、PostgreSQL、Oracle 和 BigQuery 都支持 REGEXP_REPLACE,但正则语法和参数顺序有差异。核心思路一致:用空字符串替换所有连续或单个数字字符。
最简有效模式是 [0-9](匹配任意一位数字),不是 \d——后者在 MySQL 中不被识别,在 Oracle 中需开启扩展模式,容易踩坑。
- MySQL:`REGEXP_REPLACE(str, '[0-9]', '')`
- PostgreSQL:`REGEXP_REPLACE(str, '[0-9]', '', 'g')`(必须加
'g'标志,否则只删第一个) - Oracle:`REGEXP_REPLACE(str, '[0-9]', '')`(默认全局替换)
- BigQuery:`REGEXP_REPLACE(str, r'[0-9]', '')`(需原始字符串前缀
r'')
为什么用 [0-9] 而不用 \d 或 [:digit:]?
\d 在 MySQL 中直接报错 Invalid regular expression;[:digit:] 是 POSIX 字符类,MySQL 不支持,PostgreSQL 要写成 [[:digit:]](多一层括号),Oracle 支持但不如 [0-9] 直观稳定。
实测发现:[0-9] 兼容性最好,语义明确,且不会误匹配全角数字(如“123”),这点反而是优势——如果你本就不想处理 Unicode 数字,它恰好帮你规避了编码问题。
- 要删全角数字?得额外加 Unicode 范围,例如
[0-9\uFF10-\uFF19](仅限支持 Unicode 类别的引擎,如 PostgreSQL +ICU) - 想删数字+字母?改成
[0-9a-zA-Z],但注意这会破坏原意——确认业务是否真需要“删所有字母”
性能敏感场景下的替代方案(无正则时)
如果数据库版本太老(如 MySQL 5.7 不支持 REGEXP_REPLACE),或字段量极大(千万级),正则可能变慢。这时可考虑分步 REPLACE 拼接,虽然丑但稳定:
REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(str, '0', ''), '1', ''), '2', ''), '3', ''), '4', ''), '5', ''), '6', ''), '7', ''), '8', ''), '9', '')
这个写法在 MySQL 5.7 / SQL Server 中都可用,执行计划更可控。缺点是维护成本高,且无法处理 Unicode 数字。
- 别用循环存储过程模拟正则——IO 和上下文切换开销远高于一次十层
REPLACE - 如果字段有索引,
REGEXP_REPLACE一定无法走索引;纯REPLACE链也一样,但至少不触发正则引擎编译
容易忽略的边界情况:NULL、空字符串、全数字
REGEXP_REPLACE(NULL, ...) 结果仍是 NULL,不是空字符串——如果后续要拼接或比较,得提前 COALESCE(str, '')。
另外,全由数字组成的字符串(如 '12345')会被清成空字符串 '',而非 NULL。这在 WHERE 条件里容易出错:
- 错误写法:
WHERE REGEXP_REPLACE(name, '[0-9]', '') = ''—— 会把'abc'和'123'都筛掉 - 正确写法:
WHERE name REGEXP '^[0-9]+$'单独判断是否全数字,再决定是否过滤
真正麻烦的是混合 Unicode 和 ASCII 数字的字段,比如用户从 Excel 粘贴进来的数据。这时候光靠 [0-9] 不够,但硬上 Unicode 正则又怕跨库不兼容——得先 SELECT HEX(str) 看实际字节,再决定要不要切库处理。

















