存储过程是mysql中预编译的命名sql逻辑块,支持参数、流程控制和多种返回方式;创建需改delimiter防分号误解析;参数模式in/out/inout决定数据流向;修改须drop+create;查看用show create procedure。

存储过程就是数据库里的“预编译函数”
它不是视图,也不是普通 SQL;而是一段写死在 MySQL 服务器上的、带名字的 SQL 逻辑块,创建时就完成语法检查和执行计划优化,后续调用直接走二进制路径。你可以把它理解成数据库原生支持的、能存参数、能写 if/while、能返回结果集或输出值的“本地方法”——CALL proc_name() 就是它的调用方式。
为什么非得改 DELIMITER 才能创建?
MySQL 默认把分号 ; 当作语句结束符,但存储过程中大量使用 ;(比如 SELECT ...;、SET @x = 1;),不改分隔符会导致客户端提前提交、解析失败,报错类似 ERROR 1064 (42000)。
- 必须先执行
DELIMITER //(或$、$$等非分号符号) -
CREATE PROCEDURE体内部所有语句仍用;,只有结尾的END //才触发真正执行 - 建完务必还原:
DELIMITER ;,否则后续普通 SQL 会卡住
IN/OUT/INOUT 参数到底怎么用?
这不是可有可无的修饰词,而是决定数据流向的关键标记。没声明模式的参数默认是 IN,只进不出;想从过程里拿回值,必须显式声明 OUT 或 INOUT,且调用时必须传用户变量(以 @ 开头)。
-
IN:传入值,过程内可读可改,但改了不影响外部变量 -
OUT:不关心传入值,过程内赋值后,调用方通过同名@var读取结果 -
INOUT:先传值进去,过程里可读可改,结束后外部@var被覆盖为新值 - 错误示范:
CALL proc(@x);中@x未初始化 →OUT参数会得到NULL,不是报错
删不了、改不了、查不到?这些操作陷阱最常被忽略
MySQL 不支持 ALTER PROCEDURE,也没有“编辑保存”式热更新;所谓“修改”,本质是 DROP + CREATE 两步。而查看定义必须用 SHOW CREATE PROCEDURE proc_name,SELECT * FROM information_schema.routines 只返回元信息,routine_definition 字段在 MySQL 8.0+ 才默认可见(低版本可能为空)。
- 删除前加
IF EXISTS:避免不存在时报错中断脚本 ——DROP PROCEDURE IF EXISTS proc_name - 别依赖 Workbench 的“修改”按钮:它底层仍是 drop+create,若过程正在被业务调用,中间存在空窗期
- 跨库查存储过程?
routine_schema字段必须匹配目标库名,大小写敏感(尤其在 Linux 部署环境)
真正难的从来不是写出来,而是当一个 300 行的存储过程在生产库跑着,你发现某处 WHERE 条件漏了索引字段,又不敢直接 DROP ——这时候没有调试器、没有日志输出、没有事务回滚点,只有 SELECT + ROLLBACK + 深呼吸。










