mcpField
S
sql-code-review

sql-code-review

github.com/github测试与质量40.5k14.1k 次安装今天更新
代码仓库

关于 sql-code-review

用于审查选定的 SQL,或在未选中内容时审查整个项目的技能。它围绕安全性、性能、可维护性和数据库实践整理问题,并提供可执行的建议。

主要功能

  1. 01检查 SQL 注入和访问控制
  2. 02评估查询与索引性能
  3. 03审查代码风格和模式设计
  4. 04检查数据完整性与测试
  5. 05按优先级报告问题和修复建议

适用场景

  1. 01合并前审查 SQL 变更
  2. 02查找注入风险和低效查询
  3. 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] - 设计模式、规范化
三大优先行动
  1. [关键安全修复]:解决 SQL 注入漏洞
  2. [性能优化]:添加缺失的索引或优化查询
  3. [代码质量]:改进命名规范与文档

在提供可操作、数据库无关的建议的同时,重点突出特定平台的优化与最佳实践。

评论

支持 Markdown