MySQL 8.0+支持完整正则(含^$锚点),5.7需去锚点用'13-9{9}';PostgreSQL用~匹配须TRIM()预处理;SQLite无原生正则,需扩展或LIKE组合;手机号校验应覆盖170/19x等号段并前置非空判断。

MySQL 用 REGEXP 校验手机号,但要注意版本差异
MySQL 8.0+ 原生支持 REGEXP(等价于 REGEXP_LIKE),5.7 及更早版本只支持基本正则,不支持 ^、$ 锚点和部分 Unicode 属性。直接写 phone REGEXP '^1[3-9]\d{9}$' 在老版本会静默失败或匹配异常。
- MySQL 5.7:用
phone REGEXP '1[3-9][0-9]{9}'(去掉 ^$,靠长度+前缀兜底) - MySQL 8.0+:可放心用
phone REGEXP '^1[3-9]\d{9}$',支持完整 PCRE 风格 - 注意:
REGEXP默认不区分大小写,但手机号全是数字,这点影响不大
PostgreSQL 的 ~ 和 ~* 别混用
PostgreSQL 用波浪线操作符做正则匹配,~ 区分大小写,~* 不区分。手机号字段通常是 TEXT 或 CHAR,如果数据里混入空格或换行(比如从 Excel 导入),~ '^1[3-9]d{9}$' 会直接不匹配。
- 先用
TRIM()清理:TRIM(phone) ~ '^1[3-9]d{9}$' - 若字段可能含全角数字或中文括号,得加
COLLATE "C"避免排序规则干扰匹配 - 别用
~*——它对字母敏感,但手机号没字母,纯属多余还拖慢性能
SQLite 没原生正则,LIKE 只能做简单判断
SQLite 默认不带正则函数,LIKE '1[3-9]_________' 这种写法完全无效——LIKE 的方括号是字面量,不是字符类。真要校验,只有两个现实选择:
- 启用
regexp扩展(需编译时打开或加载外部库),然后用phone REGEXP '1[3-9][0-9]{9}' - 用多个
LIKE组合兜底:phone LIKE '13%' OR phone LIKE '14%' OR ...(只覆盖前两位,再加LENGTH(phone) = 11) - 更稳妥的做法是在应用层校验,SQLite 就只存、不验
正则本身容易漏掉的边界情况
国内手机号不只有 11 位,还有虚拟运营商号段(如 170/171)、物联网卡(14x、16x)、以及新放号的 19x。单纯写 1[3-9]d{9} 会误杀 170 开头的合法号。
- 推荐用更宽松但仍有约束的模式:
'^1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])d{8}$' - 别忘了检查空值和空字符串:
phone IS NOT NULL AND phone != ''必须前置 - 如果字段类型是
INT,11 位数会溢出(MySQLINT最大 2147483647),这种字段根本没法存手机号,正则校验也就无从谈起
真正麻烦的从来不是写对那条正则,而是确认你面对的是干净字符串、明确版本、且字段类型没在背后捣鬼。










