关于 sql-insight
sql-insight 是用于 SQL 编写与分析的命令行工具,适合需要查询数据库结构、检查查询质量的开发者。它结合自然语言转 SQL、规则式优化建议和 EXPLAIN 计划解读,并提供只读与语句限制机制。
主要功能
- 01提取表结构、索引和样例数据
- 02结合数据库结构生成 SQL
- 03按 13 条规则检测查询问题
- 04运行并解读 EXPLAIN 计划
- 05只读连接与 SQL 安全限制
适用场景
- 01为自然语言请求生成 SQL
- 02检查 SQL 查询的优化问题
- 03排查全表扫描或缺失索引
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ zebbern/ claude-code-guide --skill sql-insight安装后在 Claude Code 中输入/sql-insight确认已加载。
附带文件LICENSEscripts/sql_query_helper.py
详细介绍
sql-insight
SQL 查询助手——自然语言转 SQL、查询优化分析和 EXPLAIN 执行计划解读。
功能
| 功能 | 描述 |
|---|---|
| 模式提取 | 提取数据库表结构(列、类型、索引、外键、示例数据),为自然语言转 SQL 提供上下文 |
| 自然语言 → SQL | 根据模式上下文,将自然语言描述转换为 SQL 查询 |
| 查询优化分析 | 根据 13 条规则检测 SQL 反模式,并提供优化建议 |
| EXPLAIN 解读 | 运行 EXPLAIN 并解读查询计划,识别全表扫描、缺少索引等问题 |
工作流
自然语言 → SQL
- 使用
schema命令提取数据库表结构 - 将模式用作上下文,把用户的自然语言请求转换为 SQL
- 使用
optimize命令检查生成的 SQL 是否可以改进 - 使用
explain命令验证查询执行计划
# Step 1: Extract schema (compact mode, suitable for LLM context)
python3 scripts/sql_query_helper.py --db-path data.db schema --compact
# Step 2: Analyze SQL optimization suggestions
python3 scripts/sql_query_helper.py optimize "SELECT * FROM orders WHERE user_id = 100"
# Step 3: View EXPLAIN execution plan
python3 scripts/sql_query_helper.py --db-path data.db explain "SELECT * FROM orders WHERE user_id = 100"
快速开始
模式提取
# Extract full schema (JSON format, with sample data)
python3 scripts/sql_query_helper.py --db-path data.db schema
# Compact mode (plain text, suitable for embedding in prompts)
python3 scripts/sql_query_helper.py --db-path data.db schema --compact
# Skip data sampling
python3 scripts/sql_query_helper.py --db-path data.db schema --sample-rows 0
# PostgreSQL
python3 scripts/sql_query_helper.py --db-type postgres --dsn "host=localhost dbname=mydb user=reader" schema --compact
查询优化分析
# Analyze SQL query (no database connection required, pure rule-based detection)
python3 scripts/sql_query_helper.py optimize "SELECT * FROM orders o, users u WHERE o.user_id = u.id"
python3 scripts/sql_query_helper.py optimize "SELECT name FROM users WHERE UPPER(email) LIKE '%@GMAIL.COM'"
python3 scripts/sql_query_helper.py optimize "SELECT id, (SELECT COUNT(*) FROM orders WHERE user_id = u.id) AS order_count FROM users u"
EXPLAIN 解读
# SQLite EXPLAIN
python3 scripts/sql_query_helper.py --db-path data.db explain "SELECT * FROM orders WHERE user_id = 100"
# PostgreSQL EXPLAIN
python3 scripts/sql_query_helper.py --db-type postgres --dsn "host=localhost dbname=mydb" explain "SELECT * FROM orders WHERE user_id = 100"
# PostgreSQL EXPLAIN ANALYZE (actually executes the query for real-world data)
python3 scripts/sql_query_helper.py --db-type postgres --dsn "host=localhost dbname=mydb" explain --analyze "SELECT * FROM orders WHERE user_id = 100"
详细用法
全局参数
| 参数 | 必填 | 默认值 | 描述 |
|---|---|---|---|
--db-type | 否 | sqlite | 数据库类型:sqlite 或 postgres |
--db-path | schema/explain(SQLite)时必填 | — | SQLite 数据库文件路径 |
--dsn | schema/explain(PostgreSQL)时必填 | — | PostgreSQL 连接字符串 |
子命令
| 命令 | 是否需要数据库 | 描述 |
|---|---|---|
schema | 是 | 提取数据库表结构 |
optimize <sql> | 否 | SQL 查询优化分析(纯规则检测) |
explain <sql> | 是 | 运行 EXPLAIN 并解读执行计划 |
schema 参数
| 参数 | 默认值 | 描述 |
|---|---|---|
--sample-rows, -n | 3 | 每张表的示例行数(0 表示跳过采样) |
--compact | false | 紧凑文本输出(适合嵌入提示词) |
explain 参数
| 参数 | 默认值 | 描述 |
|---|---|---|
--analyze | false | 使用 EXPLAIN ANALYZE(仅限 PostgreSQL;会实际执行查询) |
优化规则
optimize 命令会检测以下 13 种 SQL 反模式:
| 规则 | 严重程度 | 描述 |
|---|---|---|
| avoid-select-star | warning | 避免使用 SELECT *;明确列出列名 |
| unbounded-query | info | 缺少 WHERE 和 LIMIT 子句 |
| leading-wildcard-like | warning | LIKE '%...' 会导致绕过索引 |
| or-condition | info | OR 条件可能会妨碍索引使用 |
| not-in-subquery | warning | NOT IN(子查询)性能较差 |
| scalar-subquery | warning | SELECT 中的标量子查询会逐行执行 |
| function-on-column | warning | WHERE 中对列使用函数会妨碍索引使用 |
| implicit-join | info | 隐式连接(以逗号分隔的表)可读性较差 |
| distinct-usage | info | DISTINCT 可能掩盖 JOIN 导致的重复问题 |
| order-without-limit | info | ORDER BY 未配合 LIMIT 使用 |
| deep-nesting | warning | 子查询嵌套过深 |
| having-without-group | warning | HAVING 未配合 GROUP BY 使用 |
| not-equal-filter | info | != 条件无法有效使用索引 |
EXPLAIN 解读项
| 检查项 | 适用数据库 | 说明 |
|---|---|---|
| 全表扫描 | SQLite / PostgreSQL | 检测 Seq Scan / SCAN TABLE |
| 自动临时索引 | SQLite | SQLite 自动创建临时索引,表明缺少永久索引 |
| 覆盖索引 | SQLite / PostgreSQL | 索引包含所有查询列;无需查找表 |
| 磁盘排序 | PostgreSQL | 排序操作溢出到磁盘 |
| 嵌套循环连接 | PostgreSQL | 在大表上使用嵌套循环连接会导致性能不佳 |
| 行数估算偏差 | PostgreSQL (ANALYZE) | 估算行数与实际行数相差超过 10 倍 |
输出示例
schema --compact
-- Database: sqlite
-- users (1500 rows): id INTEGER PK, name TEXT, email TEXT, age INTEGER, created_at TEXT
-- IDX(unique): idx_users_email on (email)
-- orders (8200 rows): id INTEGER PK, user_id INTEGER, amount REAL, status TEXT, created_at TEXT
-- FK: user_id -> users.id
-- IDX: idx_orders_user_id on (user_id)
optimize
{
"sql": "SELECT * FROM orders o, users u WHERE o.user_id = u.id",
"issues": [
{
"severity": "warning",
"rule": "avoid-select-star",
"message": "Avoid SELECT *: only select the columns you need to reduce I/O and network transfer",
"suggestion": "Replace SELECT * with an explicit list of required column names"
},
{
"severity": "info",
"rule": "implicit-join",
"message": "Uses implicit join (comma-separated tables), which is less readable and error-prone",
"suggestion": "Use explicit JOIN ... ON syntax for better readability and maintainability"
}
]
}
explain (SQLite)
{
"db_type": "sqlite",
"query": "SELECT * FROM orders WHERE user_id = 100",
"plan": [
{"id": 2, "parent": 0, "detail": "SEARCH orders USING INDEX idx_orders_user_id (user_id=?)"}
],
"interpretation": [
{
"severity": "ok",
"type": "index-search",
"detail": "Index lookup: idx_orders_user_id",
"suggestion": "Index lookup is efficient"
}
]
}
安全机制
- 只读连接:SQLite 使用
?mode=ro;PostgreSQL 使用SET SESSION READ ONLY - SQL 白名单:仅允许以 SELECT / WITH / EXPLAIN 开头的语句
- 危险关键字拦截:拦截 INSERT、UPDATE、DELETE、DROP 及其他 30 多个关键字
- 多语句拦截:拒绝以分号分隔的多条 SQL 语句
- 标识符转义:对表名使用双引号转义,以防止 SQL 注入
依赖项
- Python 3.8+(
sqlite3是内置模块) - PostgreSQL 支持需要:
pip install psycopg2-binary optimize命令无需数据库连接,也没有外部依赖
评论
支持 Markdown