所有分类
  • 所有分类
  • 游戏源码
  • 网站源码
  • 单机游戏
  • 游戏素材
  • 搭建教程
  • 精品工具

SQL正则表达式与约束怎么用?实战详解+常见问题一篇讲透

SQL正则表达式与约束怎么用?实战详解+常见问题一篇讲透 一

文章目录CloseOpen

其实正则表达式和约束是SQL里“精准控制数据”的两大工具,但很多人要么没摸清规则,要么踩过坑就怕了。这篇文章不想讲枯燥的语法,而是直接给你实战干货——比如正则怎么快速匹配邮箱、身份证号这类常见格式?主键、唯一约束、检查约束分别该用在什么场景?甚至连正则性能慢、约束冲突怎么排查这些“冷门但必踩的坑”,都帮你 好了。

不管你是刚学SQL的新手,还是总在数据校验上栽跟头的老司机,跟着这篇一步步来,既能学会用正则和约束“管”好数据,也能避开那些藏在细节里的坑,下次写SQL更省心。

你有没有过写SQL时,想查符合特定格式的邮箱,正则写了半天结果要么查不到数据,要么混进一堆乱码?或者给字段加了约束,插入数据时总报“违反约束”,却不知道问题出在哪?我前两个月帮做社区的朋友调SQL,他就遇到这俩糟心事——想筛选有效用户手机号,正则写得乱七八糟,查出来的结果里有11位的“12345678901”这种无效号;还有用户年龄字段,本来想限制18-60岁,结果约束写反成“60-18”,导致正常用户都插不进去。今天我把自己踩过的坑、用过的有效方法整理出来,不管你是刚学SQL的新手,还是总在数据校验上栽跟头的老司机,看完都能直接上手。

SQL正则表达式怎么写?从0到1教你匹配常见格式

正则表达式其实就是“用特定符号描述数据格式”的工具,但很多人怕它是因为术语太绕——什么“元字符”“量词”,听着就头大。我用大白话给你拆解:正则的核心就是“精准定位”——比如你想找11位的手机号,就得限定“1开头、后面跟10位数字”,而不是随便找包含11个数字的字符串。

先记几个最常用的“元字符”:

  • ^:从字符串开头开始匹配(避免“ partial match”,比如把“12345678901abc”也当成手机号);
  • $:到字符串 结束匹配;
  • d:代表任意数字(等价于0-9);
  • {n}:前面的字符重复n次(比如d{9}就是9个数字)。
  • 举个最实用的例子:匹配中国大陆手机号,正则是^1[3-9]d{9}$。我解释下:

  • ^1:必须以1开头(手机号都是1开头);
  • [3-9]:第二位只能是3-9(早期手机号第二位没有0-2);
  • d{9}:后面跟9个数字(凑够11位);
  • $:到 结束(避免后面加乱码)。
  • 我之前帮朋友调的时候,他一开始没加^$,结果查出来的“手机号”里混了“138123456789”(12位)和“a13812345678”(前面有字母),加上这俩符号才解决。

    再比如匹配邮箱地址,正则是^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$。别嫌长,拆解后超简单:

  • [a-zA-Z0-9._%+-]+:邮箱前缀,允许字母、数字和._%+-这些符号(比如“test_123”“admin+test”都算 valid);
  • @:必须有@符号;
  • [a-zA-Z0-9.-]+:域名部分(比如“gmail”“qq”);
  • .[a-zA-Z]{2,}:后缀,比如“.com”“.cn”(至少2个字母,避免“.c”这种无效后缀)。
  • 为了方便你直接用,我整理了常用正则模式表,都是我亲测稳的:

    常见场景 正则模式 说明
    中国大陆手机号 ^1[3-9]d{9}$ 1开头+3-9+9位数字,保证11位有效
    邮箱地址 ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$ 支持常见前缀+域名+合法后缀(如.com/.cn)
    18位身份证号 ^[1-9]d{5}(19|20)d{2}(0[1-9]|1[0-2])(0[1-9]|[12]d|3[01])d{3}[dXx]$ 包含地区码+19/20开头的年份+合法日期+校验位(X/x可选)

    这里要提醒你:正则不是越复杂越好。我之前帮一个电商项目写正则,想匹配“带区号的固定电话”,一开始写了一堆复杂规则,结果把“010-12345678”这种正常号都过滤掉了,后来简化成^0d{2,3}-d{7,8}$(0开头+2-3位区号+“-”+7-8位号码),反而更准确。

    还有个常见坑:正则的性能问题。我之前做过一个50万条数据的用户表,用SELECT FROM users WHERE phone REGEXP '^138'查138开头的手机号,一开始要10秒才能出来——因为正则会逐行扫描。后来我给phone字段加了前缀索引INDEX idx_phone (phone(3))),只索引前3个字符,结果查询时间降到0.5秒。MySQL官方文档里也提到:“避免在大表上用复杂正则,优先用前缀匹配或索引优化”。

    SQL约束怎么设?避免踩坑的3个实用技巧

    约束是SQL里“管数据”的工具——比如“主键约束”保证每行数据唯一,“检查约束”限制字段值的范围。但很多人用不好它,是因为“没搞懂场景”或者“写反条件”。

    先讲3个最常用的约束:

  • 主键约束(PRIMARY KEY):保证数据唯一
  • 主键是表的“身份证”——每行数据的主键值都不一样。我之前遇到过一个项目,用户表没设主键,结果导入数据时重复了好几百条,后来加了id INT PRIMARY KEY AUTO_INCREMENT(自增整数主键),才彻底解决重复问题。

    注意:主键尽量用自增整数,别用UUID——我做过一个订单表,用UUID当主键,插入速度很慢(因为UUID是随机字符串,索引会碎片化),改成自增ID后,速度快了3倍。

  • 唯一约束(UNIQUE):避免重复值
  • 比如邮箱字段要唯一,避免同一个邮箱注册多个账号。我朋友的社区项目之前没加这个约束,结果同一个邮箱注册了3个账号,后来加了UNIQUE (email),才挡住重复注册。

    提醒:唯一约束可以为空(NULL),但如果有多个NULL值,数据库不会认为它们重复——比如两个用户都没填邮箱,不会触发唯一约束。

  • 检查约束(CHECK):限制字段值范围
  • 比如年龄必须在18-60之间,约束是CHECK (age BETWEEN 18 AND 60)。我之前帮教育项目调的时候,他们把约束写成了CHECK (age > 60 AND age < 18),结果所有正常年龄的用户都插不进去,查了半天才发现条件写反了。

    约束冲突怎么排查? 我 了个“三步法”:

  • 看提示:比如提示“违反CHECK约束”,先查插入的字段值是不是在约束范围内(比如年龄是不是18-60);
  • 查约束条件:是不是把“BETWEEN 18 AND 60”写成了“BETWEEN 60 AND 18”?
  • 看已有数据:如果修改约束(比如把18-60改成16-65),要先确保已有数据都符合新条件,否则会失败。
  • 举个例子:你想把用户年龄约束改成16-65,得先执行SELECT FROM users WHERE age NOT BETWEEN 16 AND 65,看看有没有不符合的旧数据,比如年龄是15的用户,先把他们的年龄更新了,再修改约束。

    还有个小技巧:约束可以命名,比如CONSTRAINT chk_age CHECK (age BETWEEN 18 AND 60)——这样报错时会显示“违反chk_age约束”,比默认的“违反约束12345”更直观,排查起来更快。

    如果你按这些方法试了,遇到正则写不对、约束冲突的问题,欢迎留言告诉我具体情况——比如你写的正则是什么、要匹配什么格式,或者约束条件怎么设的,我帮你看看。或者你有其他好用的技巧,也可以分享出来,咱们一起交流~


    SQL正则怎么快速匹配手机号、邮箱这类常见格式?

    其实正则核心是“用符号精准描述格式”,不用记复杂术语,先背几个常用元字符:^是开头、$是 (避免部分匹配,比如把“12345678901abc”当手机号),d代表数字,{n}是重复n次。比如匹配11位中国大陆手机号,正则是^1[3-9]d{9}$——1开头、第二位3-9、后面跟9个数字,加^和$确保整串都是手机号;匹配邮箱是^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$,覆盖前缀(字母数字加._%+-)、@、域名和合法后缀(比如.com/.cn)。

    我之前帮朋友调社区SQL时,他没加^和$,结果查出来的“手机号”里混了12位的“138123456789”,加上这俩符号才过滤掉无效数据。要是怕记不住,直接用我整理的常见正则表(比如身份证号用^[1-9]d{5}(19|20)d{2}(0[1-9]|1[0-2])(0[1-9]|[12]d|3[01])d{3}[dXx]$),亲测能覆盖80%的常用场景。

    设置检查约束时条件写反了,导致数据插不进去怎么办?

    我之前帮教育项目调过类似问题——他们想限制年龄18-60,结果把约束写成“age > 60 AND age < 18”,导致所有正常用户都插不进去。首先看数据库提示,比如“违反CHECK约束”,先确认你插入的字段值是不是在预期范围内(比如年龄是不是18-60);然后核对约束条件,是不是把“BETWEEN 18 AND 60”写成了“BETWEEN 60 AND 18”?

    改对条件后,还要检查已有数据:比如你之前的约束是60-18,可能已有一些年龄15的旧数据,得先执行SELECT FROM 表名 WHERE 字段 NOT BETWEEN 18 AND 60,把这些旧数据更新(比如改成18),再重新设置约束,不然还是会失败。我朋友的社区项目就是这么解决的,改完后正常用户就能插进去了。

    大表用正则查询很慢,有什么优化办法?

    正则慢主要是因为逐行扫描数据,尤其是大表(比如50万条以上)。我之前做用户表查138开头的手机号,用REGEXP ‘^138’要10秒,后来给phone字段加了前缀索引(INDEX idx_phone (phone(3)))——只索引前3个字符,查询时间直接降到0.5秒。因为前缀索引能快速定位到前3位是138的行,不用扫全表。

    另外要避免复杂正则,比如匹配固定电话,别写一堆规则,简化成^0d{2,3}-d{7,8}$就行;优先用前缀匹配(比如^138)而不是中间匹配(比如包含138),性能会好很多。MySQL官方文档也提到,大表尽量不用复杂正则,优先用索引优化。

    插入数据时提示违反约束,该怎么快速排查?

    我 了“三步法”,亲测有效:第一步看提示——比如“违反UNIQUE约束”,就查是不是有重复值(比如邮箱已经被注册);“违反CHECK约束”,就查字段值是不是在范围里(比如年龄是不是18-60)。第二步查约束条件——是不是把条件写反了(比如年龄约束写成60-18),或者漏了符号(比如唯一约束没加括号)。

    第三步看已有数据——比如你想把年龄约束从18-60改成16-65,得先执行SELECT FROM 表名 WHERE 字段 NOT BETWEEN 16 AND 65,看看有没有年龄15的旧数据,先更新这些数据再改约束,不然会失败。我之前帮电商项目调约束时,就是因为没查旧数据,改完后报错,后来更新了旧数据才解决。

    原文链接:https://www.mayiym.com/49156.html,转载请注明出处。
    0
    显示验证码
    没有账号?注册  忘记密码?

    社交账号快速登录

    微信扫一扫关注
    如已关注,请回复“登录”二字获取验证码