4. 风控用户表手机号格式校验

任务说明

对风控用户表 risk_user 中的 phone 字段做格式校验:合法手机号应为 11 位纯数字(以 1 开头)。输出所有不符合该格式的用户 user_id 与 phone,便于后续清洗或人工复核。

环境与依赖

  • MySQL 5.7+ / 8.0(使用 REGEXP 与 CHAR_LENGTH)。
  • 目标表:risk_user(user_id, phone),phone 为字符串类型(VARCHAR)。

建表与样例数据

CREATE TABLE risk_user (
  user_id BIGINT PRIMARY KEY,
  phone   VARCHAR(32)
);

INSERT INTO risk_user (user_id, phone) VALUES
(1001, '13800138000'),   -- 合法
(1002, '1380013800'),    -- 10 位,非法
(1003, '138001380000'),  -- 12 位,非法
(1004, '23800138000'),   -- 非 1 开头,非法
(1005, '1380013800a'),   -- 含字母,非法
(1006, NULL),            -- 空值,非法
(1007, '138 0013 8000'); -- 含空格,非法

校验 SQL

核心思路:用 REGEXP '^1[0-9]{10}$' 同时约束“以 1 开头 + 共 11 位数字”,再用 NOT 取反;NULL 不满足正则,需用 OR phone IS NULL 显式纳入非法集合。

SELECT user_id, phone
FROM risk_user
WHERE phone IS NULL
   OR phone NOT REGEXP '^1[0-9]{10}$';

运行与验证

  1. 执行上面的建表与插入语句,再执行校验 SQL。
  2. 预期返回 6 行:1002、1003、1004、1005、1006、1007,即除 1001 外的全部记录。
  3. 判定通过条件:结果集恰好包含上述 6 个 user_id,且不含 1001。

常见问题

  • 若 phone 为数值类型,前导 0 或超长会被截断,建议统一存为 VARCHAR。
  • MySQL 8.0 可用 REGEXP_LIKE(phone, '^1[0-9]{10}$') 替代 REGEXP,语义一致。
  • 若需兼容国际号码,应放宽正则并单独维护国家码规则,不要直接复用本校验。