应使用 sql-parser 库结构化解析 SQL 文件,提取表名及数据库名,递归处理子查询、CTE 和视图嵌套,构建反向依赖图,并结合 INFORMATION_SCHEMA 与代码扫描交叉验证,对动态 SQL、外部工具引用和触发器关联标注人工复核。

如何用 PHP 扫描 SQL 文件识别表依赖关系
PHP 本身不内置 SQL 解析器,直接用 strpos() 或正则匹配 FROM、JOIN 容易漏掉子查询、CTE、反引号包裹的表名或跨库引用。必须用结构化解析手段。
- 推荐使用
sql-parser库(GitHub 上 star 较高,支持 MySQL/PostgreSQL 基础语法),安装:composer require phpmyadmin/sql-parser - 对每个 SQL 文件调用
Parser::parse(),遍历 AST 中所有TableRef节点,提取$table->name和$table->database(如有) - 注意:UNION 内部的
FROM、WITH子句里的临时表、视图定义中的嵌套引用,都需递归解析,不能只扫第一层 - 别忽略注释干扰——
sql-parser默认跳过注释,但若 SQL 是拼接生成的(如 Laravel 的DB::raw()输出),需先做预清理
PHP 中构建反向依赖图的关键数据结构
影响分析不是单向“这个表被哪些 SQL 用”,而是“删 A 表 → 哪些视图/存储过程/ETL 脚本会崩”。必须建反向映射,且支持多级传播。
- 用
array_map+array_reduce构建二维关联:$dependents['orders'] = ['sales_report_view', 'sync_to_warehouse_proc'] - 存储过程和函数体也要解析(它们可能含动态 SQL,如
CONCAT('SELECT * FROM ', @table_name))——这类无法静态分析,需打标dynamic_sql_warning并人工复核 - 区分强依赖和弱依赖:INSERT/UPDATE/DELETE 算强依赖;SELECT 仅用于报表导出可标记为“低风险”,但需记录来源系统(如 BI 工具直连)
- 路径层级建议限制在 3 层内:A 表 → B 视图 → C 报表 → D 调度任务,超过则提示“依赖链过深,建议拆解验证”
删除前自动校验的 PHP 脚本要检查哪些硬性条件
光有依赖图不够,得结合运行时元数据交叉验证,否则会误报(比如测试环境有依赖,生产没有)或漏报(比如权限未开导致脚本从未执行)。
- 查
INFORMATION_SCHEMA.VIEWS确认视图是否真实存在且定义未失效(VIEW_DEFINITION IS NOT NULL) - 对每个依赖对象,执行
SHOW CREATE VIEW xxx或SHOW CREATE PROCEDURE xxx,重新解析一遍——避免缓存旧 AST - 检查该表是否被任何
FOREIGN KEY引用(即使没在 SQL 文件里显式出现):SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE REFERENCED_TABLE_NAME = 'target_table' - 扫描代码仓库中所有
*.php文件,grep->table('target_table')、DB::table('target_table')、FROM `target_table`,但排除// @no-bloodline注释行
为什么不能只靠 PHP 脚本完成全量影响评估
PHP 可以处理已知 SQL 文本和数据库元数据,但以下场景它看不到:
立即学习“PHP免费学习笔记(深入)”;
- BI 工具(如 Tableau、Superset)中保存的查询,未落地为文件,只存在服务端配置库
- Python/Node.js 的 ETL 任务,SQL 拼在字符串里,
eval()或exec()动态执行 - MySQL 的触发器(
TRIGGER)定义在INFORMATION_SCHEMA.TRIGGERS,但触发逻辑若含跨库操作,PHP 解析器可能无法关联到目标表 - 应用层 ORM 的软删除字段(如
is_deleted)若被当主键参与关联,删表后对应逻辑会静默失败,而非抛异常
所以最终清单必须带人工确认项:标注出“动态 SQL”、“外部工具引用”、“触发器关联”三类,这些地方 PHP 只能报警,不能替代判断。



















