mysql中用regexp判断纯数字需用'^[0-9]+$'实现全匹配,注意空格要trim()、null需is not null判断,不支持小数和科学计数法,且无法走索引,建议应用层校验更可靠。

MySQL中用REGEXP判断字符串是否为纯数字
直接结论:MySQL的REGEXP可以判断,但要注意它默认是“部分匹配”,不是“全匹配”。比如'123abc'也会被'[0-9]+'匹配成功——这不是你想要的“是否为数字”的语义。
真正可靠的写法是加上行首^和行尾$锚点:
SELECT '123' REGEXP '^[0-9]+$'; -- 1(true) SELECT '12.3' REGEXP '^[0-9]+$'; -- 0(false) SELECT ' 123 ' REGEXP '^[0-9]+$'; -- 0(false,含空格)
- 只匹配非负整数;若需支持负号,用
'^-?[0-9]+$' - 不支持小数点、科学计数法、+号前缀等;想覆盖更广,正则会迅速变复杂,且性能下降
-
REGEXP在MySQL 8.0+中底层使用ICU,行为更标准;5.7及以前用的是老式Henry Spencer引擎,对Unicode支持弱
处理带空格或前后空白的字符串
用户常忽略空格问题:' 456 '看似是数字,但^[0-9]+$直接返回0。别急着在正则里加s*——那会让' '(纯空格)也通过。
稳妥做法是先TRIM()再判断:
SELECT TRIM(' 789 ') REGEXP '^[0-9]+$'; -- 1
- 必须显式
TRIM(),因为REGEXP本身不忽略空白 - 如果字段可能为
NULL,记得加IS NOT NULL判断,否则整个表达式结果为NULL -
TRIM()在MySQL 5.7+支持;老版本可用REPLACE(REPLACE(col, ' ', ''), ' ', '')辅助清理,但不如TRIM干净
区分整数、小数、科学计数法的正则写法
业务中常需要更细粒度识别。MySQL原生REGEXP不支持d简写(5.7及以前),也不支持+量词的懒惰模式,所以得手写明确模式:
-- 非负小数(含整数):'123'、'0.45'、'.6' 都算 SELECT col REGEXP '^([0-9]+\.?[0-9]*|\.[0-9]+)$'; <p>-- 带符号浮点数(较严格):'-1.23e-4' 不支持,需拆解<br> SELECT col REGEXP '^-?[0-9]+(.[0-9]+)?$';</p>
- 小数点前可无数字(如
'.5'),但MySQL默认不认为这是合法数字字面量;业务接受就留,否则加括号限制:'^-?([0-9]+(\.[0-9]*)?|\.[0-9]+)$' - 科学计数法(如
'1e3')需额外匹配'[eE][+-]?[0-9]+',组合后正则极长,可读性差,且索引完全失效 - 若只是校验入库,建议应用层做类型转换(如PHP的
is_numeric()或Python的float()捕获异常),比在SQL里硬刚正则更稳
为什么不用CAST或CONVERT代替REGEXP?
有人试过CAST(col AS SIGNED) IS NOT NULL,但这不可靠:CAST('abc' AS SIGNED)返回0,而CAST('123abc' AS SIGNED)也返回123——它会静默截断,根本不是“是否为数字”的判断。
-
CAST(... AS DECIMAL)同样截断,且遇到非法字符时返回0或NULL(取决于SQL模式),行为不一致 -
REGEXP至少是明确的模式匹配,结果可预期;但代价是无法利用索引,WHERE条件中慎用 - 真要高性能校验,应在写入时约束(如
CHECK约束,MySQL 8.0.16+支持)或应用层过滤,而非查询时反复正则扫描
正则看着灵活,但MySQL里REGEXP的边界条件、版本差异、空格/NULL处理、性能代价,都比表面看起来麻烦得多。能提前在业务逻辑里干的事,就别塞进SQL里硬扛。











