要删的存储过程可从information_schema.routines中筛选:WHERE routine_type = 'PROCEDURE' AND routine_schema NOT IN ('mysql','information_schema','performance_schema','sys') AND (routine_name LIKE '%_tmp' OR routine_name LIKE 'old_%')。

怎么从 information_schema.routines 筛出要删的存储过程
直接查 information_schema.routines 是最稳妥的起点,但注意:它默认包含函数和过程,且不同 MySQL 版本字段名略有差异(比如 routine_type 值是 'PROCEDURE' 还是大写 'PROCEDURE')。别用模糊匹配表名,容易误伤;优先靠命名规则或创建时间过滤。
- 确认只查过程:
WHERE routine_type = 'PROCEDURE'(MySQL 8.0+ 区分大小写,建议显式写全大写) - 排除系统库:
AND routine_schema NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys') - 按命名筛(例如临时过程都带
_tmp或old_):AND routine_name LIKE '%_tmp' OR routine_name LIKE 'old_%' - 查创建时间较老的(需 MySQL 8.0+,
created字段才可靠):AND created
生成 DROP PROCEDURE IF EXISTS 脚本的正确写法
不能手拼字符串,得用 CONCAT + QUOTE 防 SQL 注入,尤其当过程名含特殊字符或空格时。漏掉 IF EXISTS 很危险——脚本重跑会报错中断;不加 QUOTE 则引号处理出错,导致生成语句语法错误。
- 基础模板:
SELECT CONCAT('DROP PROCEDURE IF EXISTS ', QUOTE(CONCAT(routine_schema, '.', routine_name)), ';') AS drop_stmt FROM information_schema.routines WHERE ... - 务必对
routine_schema和routine_name同时QUOTE,避免跨库名解析失败 - 结果导出后,先人工扫一眼,确认没混进函数(
routine_type漏过滤)或系统过程
执行前必须验证的三件事
批量删过程不是“生成完就运行”,中间有不可逆风险。最容易踩的坑是:在从库上执行、没检查依赖、忽略权限限制。
- 确认当前连接的是主库(
SELECT @@read_only;应为0) - 检查是否有视图/事件/其他过程调用目标过程:
SELECT * FROM information_schema.routines WHERE routine_definition LIKE '%your_proc_name%';(注意大小写和空格) - 确保账号有
ALTER ROUTINE权限,否则DROP会报ERROR 1227 (42501): Access denied
MySQL 5.7 和 8.0 在 routines 表上的关键差异
如果你的环境横跨多个版本,字段可用性直接影响脚本能用不能用。5.7 没 created 和 last_altered,只能靠名字或注释推断;8.0 的 routine_comment 可能存着“deprecated”标记,值得扫一遍。
- MySQL 5.7:
information_schema.routines缺少created、last_altered字段,无法按时间筛选 - MySQL 8.0:
routine_comment字段可读,适合 grep “deprecated” 或 “legacy” - 统一兼容写法:用
routine_schema+routine_name做唯一标识,别依赖specific_name(它在 5.7 不稳定)
实际跑脚本时,最常被跳过的步骤是人工核对生成的 DROP 语句——哪怕只删 3 个,也值得粘贴到客户端里 SELECT 一下再执行。名字相似、大小写混用、测试库同步残留,这些细节不会报错,但删错就回不去了。










