导读:本期聚焦于小伙伴创作的《如何编写带输入校验的SQL存储过程?用正则或LIKE匹配实现》,敬请观看详情。把非法参数挡在数据库门外,靠存储过程内的输入校验最稳妥。直接拼接SQL容易注入,若在过程开头用正则或LIKE做格式核对,不合规的数据立刻报错退出。以MySQL为例,REGEXP可验邮箱手机,LIKE适合前缀模糊比。本文对比两种写法差异,给出完整过程模板与调用示例,说明何时选正则、何时用LIKE更省资源,帮你在写过程时少踩坑。

在后台系统里,存储过程常直接接收前端传来的参数去做增删改查。如果不在过程内部先核对参数合法性,脏数据或恶意字符串就会流进表里面。编写带输入校验的SQL存储过程,核心思路是在真正执行业务SQL之前,用正则表达式或者LIKE匹配对入参做格式检查,不通过就主动报错并结束。

为什么要在存储过程里做输入校验

很多人习惯把校验放在应用层,比如用Java或Python先判断再调数据库。但多端共用同一个库时,网页、小程序、定时脚本都可能直接调用存储过程,应用层拦不住全部入口。把校验下沉到存储过程,相当于在数据库门口设了一道统一关卡,无论谁调用都必须过检。

另一个现实问题是SQL注入。拼字符串执行虽然方便,但遇到特殊字符就危险。存储过程本身参数化执行更安全,若再配合输入格式校验,能进一步缩小被攻击面。比如要求用户名只能含字母数字,用正则一匹配,带分号或引号的统统进不来。

使用LIKE匹配实现简单校验

LIKE适合做前缀、后缀或包含关系的模糊匹配,语法简单、各数据库都支持,性能也轻。比如只允许以A开头的订单号,或者参数里不能出现某些关键词,用LIKE配合通配符就很直观。它不支持复杂规则,但应对基础格式够用。

下面以MySQL为例,写一个校验用户名只能以字母开头、且不含空格的存储过程。我们用LIKE '% %'判断是否有空格,再用LEFT取首字符看是不是字母。虽然不如正则严谨,但逻辑清楚,初学者也容易改。

DELIMITER $$

CREATE PROCEDURE add_user_if_valid (
    IN p_username VARCHAR(50)
)
BEGIN
    -- 若包含空格则非法
    IF p_username LIKE '% %' THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '用户名不能包含空格';
    END IF;

    -- 首字符不是字母则非法
    IF p_username NOT REGEXP '^[A-Za-z]' THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '用户名必须以字母开头';
    END IF;

    INSERT INTO users(username) VALUES (p_username);
END$$

DELIMITER ;

上面例子里其实混用了一点正则,纯粹LIKE版本可以写成判断首字符用子串函数。LIKE的优势是可读,缺点是对“只能由某几类字符组成”这种全串规则表达力弱,写多了嵌套会乱。

使用正则表达式做严格校验

MySQL、PostgreSQL、Oracle都支持REGEXP或相似正则语法,能描述整串规则。比如邮箱、手机号、身份证,用一条正则比写一堆LIKE直观得多。正则代价是稍多一点计算,但在入参长度有限时影响很小。

以下过程要求传入的手机号必须是11位数字且以1开头,否则报错。正则'^1[0-9]{10}$'直接从头到尾锁定格式,避免中途混字母。

DELIMITER $$

CREATE PROCEDURE save_phone_if_valid (
    IN p_phone VARCHAR(20)
)
BEGIN
    IF p_phone NOT REGEXP '^1[0-9]{10}$' THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '手机号格式不正确';
    END IF;

    INSERT INTO contact(phone) VALUES (p_phone);
END$$

DELIMITER ;

正则写错了容易让合法数据被拒,所以规则要确定再上线。建议把正则串提取成过程顶部变量或注释写明含义,方便后续维护。PostgreSQL里用的是~操作符,Oracle可用REGEXP_LIKE函数,思路一致。

正则与LIKE怎么选

从场景看,LIKE适合模糊、简单、可读性优先的校验;正则适合强格式、精确全串匹配。若表量大且过程被高频调用,LIKE通常更省CPU。但像邮箱这种规则,硬用LIKE要拆好几段,反而更难懂。

对比项LIKE正则表达式
语法复杂度中高
表达全串规则
数据库支持全部主流均支持
性能开销较小略大

实际项目常组合使用:先用LIKE挡掉明显异常,再用正则做精细核对。这样既不牺牲太多性能,也保住校验强度。

完整可运行示例

下面给一个综合例子,过程接收邮箱与年龄,邮箱用正则、年龄用范围加LIKE无关判断,展示如何在一个过程里组织多条校验并给出明确错误。

DELIMITER $$

CREATE PROCEDURE register_user (
    IN p_email VARCHAR(100),
    IN p_age INT
)
BEGIN
    IF p_email NOT REGEXP '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$' THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '邮箱格式不合法';
    END IF;

    IF p_age < 1 OR p_age > 150 THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '年龄超出合理范围';
    END IF;

    INSERT INTO account(email, age) VALUES (p_email, p_age);
END$$

DELIMITER ;

调用时若传错邮箱会直接收到报错,不会插进表。注意代码里把小于号写成<、大于号写成>,避免被当标签解析。这种写法在各类SQL教程里都算规范做法。

常见误区与注意点

有人喜欢在过程里用SELECT拼字符串再PREPARE EXECUTE,这时校验再严也要防引号逃逸。本文示例都用参数化INSERT,天然隔离。另外 SIGNAL 抛错要在支持的事务上下文里,若外层没捕获,调用端会收到异常,属正常表现。

还有一点,正则在不同数据库里元字符略有差异,比如MySQL用双反斜杠表示转义,PostgreSQL单斜杠即可。写跨库脚本时要分别测试,不要假定一套正则通吃。先把输入校验写稳,再谈业务逻辑的复杂度。

SQL存储过程输入校验正则表达式修改时间:2026-08-06 02:12:59

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。