关于 sql-code-review
用于审查选定的 SQL,或在未选中内容时审查整个项目的技能。它围绕安全性、性能、可维护性和数据库实践整理问题,并提供可执行的建议。
主要功能
- 01检查 SQL 注入和访问控制
- 02评估查询与索引性能
- 03审查代码风格和模式设计
- 04检查数据完整性与测试
- 05按优先级报告问题和修复建议
适用场景
- 01合并前审查 SQL 变更
- 02查找注入风险和低效查询
- 03评估模式、索引和数据完整性
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ github/ awesome-copilot --skill sql-code-review安装后在 Claude Code 中输入/sql-code-review确认已加载。
详细介绍
SQL 代码审查
对 ${selection}(如果未选择,则为整个项目)进行全面的 SQL 代码审查,重点关注安全性、性能、可维护性和数据库最佳实践。
🔒 安全性分析
SQL 注入防护
-- ❌ CRITICAL: SQL Injection vulnerability
query = "SELECT * FROM users WHERE id = " + userInput;
query = f"DELETE FROM orders WHERE user_id = {user_id}";
-- ✅ SECURE: Parameterized queries
-- PostgreSQL/MySQL
PREPARE stmt FROM 'SELECT * FROM users WHERE id = ?';
EXECUTE stmt USING @user_id;
-- SQL Server
EXEC sp_executesql N'SELECT * FROM users WHERE id = @id', N'@id INT', @id = @user_id;
访问控制与权限
- 最小权限原则:只授予所需的最低权限
- 基于角色的访问:使用数据库角色而非直接的用户权限
- Schema 安全:正确的 schema 所有权和访问控制
- 函数/存储过程安全:审查 DEFINER 与 INVOKER 权限
数据保护
- 敏感数据暴露:避免对包含敏感列的表执行 SELECT *
- 审计日志:确保敏感操作被记录
- 数据脱敏:使用视图或函数对敏感数据脱敏
- 加密:验证敏感数据是否加密存储
⚡ 性能优化
查询结构分析
-- ❌ BAD: Inefficient query patterns
SELECT DISTINCT u.*
FROM users u, orders o, products p
WHERE u.id = o.user_id
AND o.product_id = p.id
AND YEAR(o.order_date) = 2024;
-- ✅ GOOD: Optimized structure
SELECT u.id, u.name, u.email
FROM users u
INNER JOIN orders o ON u.id = o.user_id
WHERE o.order_date >= '2024-01-01'
AND o.order_date < '2025-01-01';
索引策略审查
- 缺失索引:找出需要建立索引的列
- 索引过多:发现未使用或冗余的索引
- 复合索引:为复杂查询建立多列索引
- 索引维护:检查是否存在碎片化或过期的索引
连接优化
- 连接类型:验证连接类型是否恰当(INNER vs LEFT vs EXISTS)
- 连接顺序:优先优化结果集较小的部分
- 笛卡尔积:找出并修复缺失的连接条件
- 子查询与 JOIN:选择最高效的方式
聚合函数与窗口函数
-- ❌ BAD: Inefficient aggregation
SELECT user_id,
(SELECT COUNT(*) FROM orders o2 WHERE o2.user_id = o1.user_id) as order_count
FROM orders o1
GROUP BY user_id;
-- ✅ GOOD: Efficient aggregation
SELECT user_id, COUNT(*) as order_count
FROM orders
GROUP BY user_id;
🛠️ 代码质量与可维护性
SQL 风格与格式
-- ❌ BAD: Poor formatting and style
select u.id,u.name,o.total from users u left join orders o on u.id=o.user_id where u.status='active' and o.order_date>='2024-01-01';
-- ✅ GOOD: Clean, readable formatting
SELECT u.id,
u.name,
o.total
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.status = 'active'
AND o.order_date >= '2024-01-01';
命名规范
- 命名一致:表、列、约束遵循一致的命名模式
- 名称具有描述性:为数据库对象使用清晰、有意义的名称
- 保留字:避免使用数据库保留字作为标识符
- 大小写敏感:在整个 schema 中保持一致的大小写用法
Schema 设计审查
- 范式化:采用适当的范式化程度(避免过度或不足)
- 数据类型:为存储和性能选择合适的数据类型
- 约束:正确使用 PRIMARY KEY、FOREIGN KEY、CHECK、NOT NULL
- 默认值:为列设置合适的默认值
🗄️ 特定数据库的最佳实践
PostgreSQL
-- Use JSONB for JSON data
CREATE TABLE events (
id SERIAL PRIMARY KEY,
data JSONB NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- GIN index for JSONB queries
CREATE INDEX idx_events_data ON events USING gin(data);
-- Array types for multi-value columns
CREATE TABLE tags (
post_id INT,
tag_names TEXT[]
);
MySQL
-- Use appropriate storage engines
CREATE TABLE sessions (
id VARCHAR(128) PRIMARY KEY,
data TEXT,
expires TIMESTAMP
) ENGINE=InnoDB;
-- Optimize for InnoDB
ALTER TABLE large_table
ADD INDEX idx_covering (status, created_at, id);
SQL Server
-- Use appropriate data types
CREATE TABLE products (
id BIGINT IDENTITY(1,1) PRIMARY KEY,
name NVARCHAR(255) NOT NULL,
price DECIMAL(10,2) NOT NULL,
created_at DATETIME2 DEFAULT GETUTCDATE()
);
-- Columnstore indexes for analytics
CREATE COLUMNSTORE INDEX idx_sales_cs ON sales;
Oracle
-- Use sequences for auto-increment
CREATE SEQUENCE user_id_seq START WITH 1 INCREMENT BY 1;
CREATE TABLE users (
id NUMBER DEFAULT user_id_seq.NEXTVAL PRIMARY KEY,
name VARCHAR2(255) NOT NULL
);
🧪 测试与验证
数据完整性检查
-- Verify referential integrity
SELECT o.user_id
FROM orders o
LEFT JOIN users u ON o.user_id = u.id
WHERE u.id IS NULL;
-- Check for data consistency
SELECT COUNT(*) as inconsistent_records
FROM products
WHERE price < 0 OR stock_quantity < 0;
性能测试
- 执行计划:审查查询执行计划
- 负载测试:使用真实数据量测试查询
- 压力测试:验证并发负载下的性能
- 回归测试:确保优化不会破坏功能
📊 常见反模式
N+1 查询问题
-- ❌ BAD: N+1 queries in application code
for user in users:
orders = query("SELECT * FROM orders WHERE user_id = ?", user.id)
-- ✅ GOOD: Single optimized query
SELECT u.*, o.*
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;
滥用 DISTINCT
-- ❌ BAD: DISTINCT masking join issues
SELECT DISTINCT u.name
FROM users u, orders o
WHERE u.id = o.user_id;
-- ✅ GOOD: Proper join without DISTINCT
SELECT u.name
FROM users u
INNER JOIN orders o ON u.id = o.user_id
GROUP BY u.name;
WHERE 子句中函数误用
-- ❌ BAD: Functions prevent index usage
SELECT * FROM orders
WHERE YEAR(order_date) = 2024;
-- ✅ GOOD: Range conditions use indexes
SELECT * FROM orders
WHERE order_date >= '2024-01-01'
AND order_date < '2025-01-01';
📋 SQL 审查清单
安全性
- 所有用户输入都已参数化
- 没有使用字符串拼接构建动态 SQL
- 具备适当的访问控制和权限
- 敏感数据得到妥善保护
- SQL 注入攻击途径已消除
性能
- 频繁查询的列已建立索引
- 没有不必要的 SELECT * 语句
- JOIN 已优化并使用恰当的类型
- WHERE 子句具有选择性并使用索引
- 子查询已优化或转换为 JOIN
代码质量
- 命名规范一致
- 格式和缩进正确
- 复杂逻辑有有意义的注释
- 使用了合适的数据类型
- 实现了错误处理
Schema 设计
- 表已正确范式化
- 约束保障数据完整性
- 索引支持查询模式
- 已定义外键关系
- 默认值恰当
🎯 审查输出格式
问题模板
## [PRIORITY] [CATEGORY]: [Brief Description]
**Location**: [Table/View/Procedure name and line number if applicable]
**Issue**: [Detailed explanation of the problem]
**Security Risk**: [If applicable - injection risk, data exposure, etc.]
**Performance Impact**: [Query cost, execution time impact]
**Recommendation**: [Specific fix with code example]
**Before**:
```sql
-- Problematic SQL
```
**After**:
```sql
-- Improved SQL
```
**Expected Improvement**: [Performance gain, security benefit]
总体评估
- 安全评分:[1-10] - SQL 注入防护、访问控制
- 性能评分:[1-10] - 查询效率、索引使用
- 可维护性评分:[1-10] - 代码质量、文档
- Schema 质量评分:[1-10] - 设计模式、规范化
三大优先行动
- [关键安全修复]:解决 SQL 注入漏洞
- [性能优化]:添加缺失的索引或优化查询
- [代码质量]:改进命名规范与文档
在提供可操作、数据库无关的建议的同时,重点突出特定平台的优化与最佳实践。
评论
支持 Markdown