SQL 审查 (sql-review)
一句话定位
写 SQL 之后、上线之前的静态体检——不连库、不执行,只扫文本,拦住性能反模式、注入风险和危险操作。
适用场景
- 写完一段 SQL,提交 / 提 MR 前想先自查
- 给报表、接口、ETL 任务写的查询,担心慢、担心全表扫描
- 接手别人的 SQL,快速找出隐患
- 代码评审里对 SQL 片段做自动检查
不适用(请改用其他技能)
- 需要真实执行计划、索引建议、改写后 SQL →
sql-optimizer(问答式、需表结构、偏性能调优) - 需要连接生产库做语义/数据校验 → 不在本技能范围
三子命令
1. check — SQL 审查主流程
# 审查文件(可多次 --path)
python3 sql_review.py check --path query.sql --path another.sql
# 直接传 SQL
python3 sql_review.py check --sql "SELECT * FROM t WHERE id = '" + x
# JSON 输出(便于 CI 集成)
python3 sql_review.py check --path query.sql --json
输出每个问题:[FAIL]/[REVIEW] L行号 规则码 说明 + 修复建议。
- FAIL:注入风险 / 危险操作(DROP、TRUNCATE、无 WHERE 的 DELETE/UPDATE、字符串拼接 SQL、动态表名、EXECUTE 动态执行)
- REVIEW:性能反模式 / 规范(SELECT *、缺 LIMIT、前导通配符 LIKE、OR 滥用、NOT IN 子查询、ORDER BY RAND、函数包裹索引列、保留字作标识符)
- 整体结论三态:PASS / REVIEW / FAIL
2. validate — 单语句基础校验
python3 sql_review.py validate --path query.sql
python3 sql_review.py validate --sql "SELECT (a FROM t"
检查:非空、以已知 SQL 关键字开头、括号配对。退出码 0=PASS / 2=FAIL。
3. compatibility — 方言兼容性诊断
python3 sql_review.py compatibility --path query.sql --dialect postgresql
# dialect: postgresql | sqlite | mysql
检测目标方言不兼容写法(反引号标识符、LIMIT a,b 分页、IFNULL、TOP n、AUTO_INCREMENT 等)。
退出码
| 退出码 | 含义 |
|---|---|
| 0 | 全部通过 (PASS) |
| 1 | 存在需审查项 REVIEW,无 FAIL |
| 2 | 存在 FAIL,或参数/文件错误(含未知方言) |
规则清单(覆盖范围)
| 类别 | 规则码 | 级别 |
|---|---|---|
| 性能 | SELECT_STAR / MISSING_LIMIT / LIKE_LEADING_WILDCARD / OR_ABUSE / NOT_IN_SUBQUERY / ORDER_BY_RAND / FUNC_ON_COLUMN | REVIEW |
| 安全 | STRING_CONCAT_SQL / DYNAMIC_TABLE_NAME / EXEC_DYNAMIC_SQL | FAIL |
| 危险 | DELETE_NO_WHERE / UPDATE_NO_WHERE / DANGEROUS_DDL | FAIL |
| 规范 | RESERVED_WORD_IDENTIFIER | REVIEW |
设计原则与边界
- 纯标准库,零第三方依赖,不联网,不连接任何数据库,绝不执行 SQL 文本。
- 静态分析,基于文本规则匹配,不依赖表结构、统计信息或执行计划——因此不产出索引建议、不估算真实代价(那是
sql-optimizer的领域)。 - 误报可控:规则为高确定性模式;
MISSING_LIMIT对子查询/视图定义可能误提示,已标注"若确为全量导出请忽略"。 - 合规红线:只做代码静态自查,不判断业务正确性、不下架构结论。
输入要求
check/validate/compatibility接受--path 文件.sql或--sql "..."内联。- 支持
--行注释与/* */块注释(扫描前剥离,避免注释内片段误报)。 - 文件名与内容均使用 ASCII / UTF-8,无特殊编码要求。