Community写作与编辑github.com

royashbrook/sql-spider

确定性SQL依赖关系图提取器和蜘蛛式闭包映射器。可插拔的多方言支持,可选的graphify导出。即插即用的Agent技能。

sql-spider 是什么?

sql-spider 是一个确定性 SQL 依赖关系图提取工具,它通过解析 SQL 文本的抽象语法树(AST)来构建依赖图,无需连接数据库即可工作。该工具的核心机制是“蜘蛛闭包”:从一个种子对象(如表或存储过程)出发,逐步向外扩展,直到所有依赖对象形成一个完整的连通分量。整个过程是纯离线且可重现的——相同的输入总是产生相同的输出图。 此技能适用于多种AI Agent平台(如Claude Code、Cursor、Codex等),支持T-SQL、SQLite等多种SQL方言。它的工作方式是通过生成只读SQL查询,然后由Agent(或用户)手动运行这些查询并将结果以CSV格式反馈,从而驱动整个循环。这个设计使其特别适合无法直接连接数据库、只能通过只读作业或DBA中间人访问的场景。 sql-spider 的主要价值在于帮助开发者理解遗留数据库的依赖关系:回答“哪个表/存储过程引用了Orders?”、“某个存储过程的完整依赖闭包是什么?”等问题。它提供命令行界面用于提取、种子播种、吸收和可视化,并可选集成graphify工具生成可查询的知识图谱。该工具严格遵守只读原则,不会对数据库进行任何写入操作。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add royashbrook/sql-spider

Installed? Explore more 写作与编辑 skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

sql-spider 是做什么的?

构建 SQL 数据库的确定性依赖关系图,并从种子对象开始向外“蜘蛛式”扩展,直到闭合:形成一个连通分量,零孤立对象,无幻象边。图引擎是纯离线的:它将 SQL 文本解析为 AST 并直接从语法树中读取依赖关系,因此相同的输入总是产生相同的图,无需任何启发式规则,也无需实时连接。

此技能存在的核心原因:sql-spider 从不连接数据库。 它仅发出只读查询并接收 CSV 结果。因此,你,作为 Agent,就是数据库适配器。 你需要以任何能访问数据库的方式运行每个发出的查询,将结果反馈回来,并驱动整个循环。这正是它的设计初衷(映射仅通过只读作业可达的数据库,从未直接连接),也是该工具可以安全地指向任何数据库的原因。

何时使用

  • “映射这个数据库” / “为我构建这些存储过程/表/视图的依赖关系图。”
  • “什么引用了 Orders?” / “proc_x 实际上会触及哪些对象?”
  • “查找这个表的完整闭包”:它所有传递性依赖,直到没有遗漏。
  • “我无法直接访问数据库,发出查询我来运行,”或“请发给 DBA。”
  • 文档化/理解一个遗留模式,无人知晓哪些依赖于哪些。

不适合:编写应用程序 SQL、更改数据或模式(此技能为只读,参见护拦规则),或任何需要变更数据库的操作。

工作原理(契约)

引擎是方言无关的。唯一与方言相关的步骤是将 .sql 解析为依赖事实(通过一个单方法接口 IDialectExtractor)。其他所有操作都是方言中立的:图组装、前沿(frontier)、蜘蛛循环、连通分量闭包审计、血统、可视化。

无论方言或数据库如何,循环始终具有相同的形状:

  1. seed(种子)/ round(轮次) 将只读 .sql 查询文件输出到输出目录。
  2. 你 针对数据库运行这些查询(适配器步骤),并将每个结果保存为 CSV 文件。
  3. absorb(吸收) 将 CSV 文件折叠回语料库,作为 .sql 文件。
  4. round(轮次) 重新提取,写出一个图和一个 HTML 可视化文件,并暂存下一轮拉取查询,或报告闭包。
  5. 重复直到前沿为空且图是一个连通分量。

第一步:安装,不要仅运行(一次性)

如果您通过原始抓取(用户粘贴了 "fetch .../SKILL.md and follow it")或以非标准方式检出此文件并未将其放入您的技能目录,请在使用前安装它,将仓库克隆到您的技能目录,然后从安装的副本继续操作:

git clone https://github.com/royashbrook/sql-spider ~/.claude/skills/sql-spider   # Claude Code
# 其他环境:克隆到您的技能自动发现的路径下

然后告知用户您已安装。区别在于:就地运行(或原始抓取)今天可用但明天被遗忘;安装后,每个未来会话都会自动发现该能力。将“使用此工具”视为包含安装步骤。

对于 graphify 配对(第 6 步)也是如此:graphify 的安装是两条命令(uv tool install graphifyy 安装二进制文件,然后 graphify install --platform <your harness> 注册 graphify 自己的技能)。仅安装二进制文件是最常见的遗漏;请务必执行两者。

第 0 步:构建一次(首次使用构建)

此技能提供的是 .NET 源代码,而非二进制文件。首次调用时构建;后续调用重用构建产物。需要 .NET 10 SDK(dotnet --version;如果缺失,请安装:macOS 上使用 brew install dotnet,其他系统使用发行版包,或访问 https://dot.net)。

将 SKILL_DIR 解析为包含此文件的目录,然后定义一条命令:

SKILL_DIR="<此技能目录的绝对路径>"
spider() { dotnet run -c Release --project "$SKILL_DIR" -- "$@"; }

第一次 spider ... 调用会进行编译(几秒钟,恢复 ScriptDom + SqlParserCS);之后每次调用都很快。在接触真实数据库前,通过捆绑的示例进行迎检测试:

spider extract "$SKILL_DIR/examples/northwind"   # -> 36 个节点,66 条边,“一个分量,零个孤立对象”
spider viz "$SKILL_DIR/examples/northwind/graph.json" && open "$SKILL_DIR/examples/northwind/graph.html"

如果输出 OK: single connected component, no orphans,则工具可以正常工作。

第 1 步:选择适配器(您将如何访问数据库?)

sql-spider 发出查询;需要有人运行它们。在播种之前决定您是谁(完整说明见 references/adapters.md):

  • 连接式 SQL 工具 / MCP: 您有一个运行查询并返回行的工具。您运行每个发出的 .sql 文件并将结果行写为 CSV。最快;当 Agent 可以访问数据库时最佳。
  • 只读查询桥: 一个任务/技能,您放入 .sql 文件,它对数据库运行,返回 CSV(这是原始设置,一个具有只读权限的 CI 任务)。您通过它调度每个发出的查询并收集 CSV。
  • 用户运行它们: 您根本无法访问数据库。您打印每个查询,用户在其客户端(SSMS,sqlcmd 等)中运行,并将 CSV 结果粘贴回来。最慢,但在任何地方都有效,并且是针对锁定生产数据库的正确做法(用户或其 DBA 批量运行)。

无论是什么,契约都是相同的:发出的 .sql 文件输入,CSV 输出。选择一个并在整个运行过程中保持不变。

第 2 步:设置工作目录

在技能目录之外工作,以保持技能仓库干净。在用户的项目(或任何临时目录)中:

mkdir -p work/corpus work/stage && cd work

corpus/ 保存累积的 .sql 文件(当前的模型);stage/ 是当前轮次查询及其 CSV 文件所在的位置。

第 3 步:从根对象播种

选择一个用户关心的根对象,一个核心表或存储过程。从此处冷启动:

spider seed Orders stage/           # 将只读拉取查询写入 stage/

seed 发出用于拉取根对象自身定义、其模式(如果是表)以及所有引用它的对象的查询。通过您的适配器(第 1 步)运行这些查询,将每个结果保存为 stage/ 中的 CSV 文件,然后将其折叠进来:

spider absorb stage/*.csv --corpus corpus/

第 4 步:轮次直到闭包(每次一个可审查的轮次)

spider round corpus/

每一轮:从 corpus/ 重新提取到 corpus/graph.json,写入 corpus/graph.html(打开以审查),然后要么报告闭包,要么在 corpus/_next/ 中暂存下一轮拉取查询。如果仍有前沿:

# 通过您的适配器运行 corpus/_next/*.sql,将 CSV 保存到 corpus/_next/,然后:
spider absorb corpus/_next/*.csv --corpus corpus/
spider round corpus/      # 再次

每次轮次前沿都会缩小。默认一次运行一轮,以便人员可以打开可视化文件并决定是否继续拉取,尤其是在生产环境中。持续运行直到 round 报告前沿为空。

第 5 步:闭包

当前沿为空且图是一个连通分量且零孤立对象时,您就完成了。闭包审计是关口;extract 在图尚未闭合时甚至返回非零退出码,因此可以集成到 CI 中。

一个作用域说明:节点标识是数据库作用域内的裸名称(架构前缀被丢弃),因此一次蜘蛛运行映射一个数据库。如果用户的问题跨架构或数据库,则为每个作用域运行一次循环,使用第一个闭合图的边界边(指向外部的引用)作为下一个扫描的种子,然后按节点 ID 合并生成的 graph.json 文件(graphify merge-graphs,或一个小型 JSON 并集)。您可以自行驱动整个序列;不需要新的工具。

并非所有对象都能通过边闭合,这没问题:真正独立的对象(仅由应用程序使用的函数、版本/归档表仅在数据库外部被引用)会被附上理由报告,而不是作为错误。诚实的约束是“来自提取遗漏的零孤立对象”:当一个节点被隔离时,审计会告诉您它是需要拉取的真正缺口还是真正的独立对象。

第 6 步:查看,并(可选)交接给 graphify

您已经拥有一个查看器,无需安装:spider viz <graph.json> 会写入一个自包含的交互式 HTML 文件(力导向图、可拖拽、按类型着色)。在任何浏览器中打开。对于大多数使用场景,这就是您需要的全部。

如果已安装 graphify,请主动向用户提议将闭合图交给它处理。 graphify (https://github.com/safishamsi/graphify) 可以将图转换为可查询的知识图谱,支持社区检测和 query / path / explain 功能。作为 Agent,请检查它是否可用(PATH 中存在 graphify 命令、存在 graphify 技能,或项目中已有 graphify-out/ 目录),如果是,请询问用户是否要同时输出 graphify 视图并将其转交。如果未安装,请提议安装,如果用户同意,请安装两个部分,即二进制文件和技能(uv tool install graphifyy,然后 graphify install --platform <your harness>)。第二条命令使 graphify 在将来的会话中可被发现;仅安装二进制文件是最常见的遗漏。

使用 --graphify,不要将原生的 graph.json 复制到 graphify 中。 原生图是一个有向多重图;直接交给 graphify 会导致被低估。--graphify 标志会写入一个单独的、graphify 格式的文件,而不影响原生 graph.json:

spider extract corpus/ --graphify     # 写入原生 graph.json 和 graphify-out/graph.json
graphify cluster-only corpus/          # 聚类 + 报告(或 /graphify 的子命令)

两件值得了解的事情,均来自实际运行经验:

  • 关系词汇(默认保留我们自己的)。 默认情况下,投影保留 sql-spider 自己的关系(fk / references / writes / calls / join_key)。graphify 可以很好地接收它们,并且读/写分离是回答“什么实际上更新了这张表”最有用的信号。添加 --graphify-standard 以折叠为 graphify 标准枚举(references / calls / shares_data_with),这在合并多个数据库并希望统一词汇时很有用。
  • 询问一张表是如何被使用的。 使用 graphify 的 explain X,而不是 query X。被引用的表是接收端(边指向内部),因此 query(向外遍历)仅返回表本身,而 explain 会显示回答该问题的入边。
  • 为社区命名。 聚类会产生占位符标签(“社区 7”),一个包含 50 多个未命名聚类的图对您要交付的最终用户来说是不可读的。您几乎总能从成员中推断出真实名称:主要的表名前缀、枢纽对象以及集群中存储过程的实际功能(计费、派单、评分、审计)。在 cluster-only 之后,读取每个社区的成员列表并重命名为简短的、反映领域真实情况的标签(编辑 graphify 的 graph.json / 报告中的社区标签)。花十分钟命名是让图所有者能够导航还是只有您能理解的关键区别。主动提议;用户会同意。

在我们自己的使用中,我们将一个计费子系统映射为闭合图,并直接从中回答了“什么依赖于这个”的问题,仅打开了图中指向的那个存储过程。graphify 自己的文档涵盖了知识图谱为您带来的其他好处。如果 graphify 未安装,请跳过所有这些;viz 已经显示了图,sql-spider 的任务在闭合后即告完成。

护拦规则

  • 始终只读。 每个发出的查询都是一个带有 no-lock / 死锁受害者 / set nocount on 安全前言的 select。永远不要将其编辑为写入操作。永远不要通过此技能运行 insert / update / delete / merge / DDL。如果您在组合任何非只读操作,您就在使用错误的工具。
  • 针对生产环境,控制节奏。 不要自动向生产数据库发送大量查询。一次运行一个可审查的轮次,或将暂存的查询交给用户/DBA 进行批量运行。仅在适配器可以安全无人值守运行且数据库所有者同意的情况下,才适合自动循环(round 直到闭包)。
  • 图是比主体更安全的工件。 依赖关系图(对象名称 + 边)是持久化的输出。corpus/ 中拉取到的存储过程主体是目标组织的内部逻辑。请将该语料库视为私有;发布图,而不是主体。

子命令

命令功能
extract <corpus-dir> [graph.json] [frontier.json] [--dialect tsql|sqlite] [--graphify[=out.json]] [--graphify-standard]将 *.sql 解析为依赖图 + 前沿 + 审计;--graphify 同时写入 graphify 格式的图(--graphify-standard 使用 graphify 的标准关系词汇)
seed <root-object> <outdir>在空语料库上为一个根对象冷启动拉取查询
generate <frontier.json> <outdir>为当前前沿生成前向拉取查询
reverse <referencers.csv> <outdir> [--roots a b]拉取引用根对象的对象模块定义(一个反向层次)
absorb <csv...> --corpus <dir>将拉取的 CSV 文件折叠回语料库作为 .sql 文件
viz <graph.json> [out.html]将图渲染为自包含的交互式 HTML 文件
round <corpus-dir> [--dialect ...]一个可审查的蜘蛛遍历轮次:提取 → 图 + 可视化 → 暂存下一轮查询(或报告闭包)

round 是循环驱动程序;其他命令是它组合的部分(以及您在冷启动时使用 seed 直接调用,或使用 generate / reverse 手动遍历时调用的部分)。

方言

--dialect tsql(默认)使用 Microsoft ScriptDom 进行解析(完全的 T-SQL 保真度)。--dialect sqlite 使用 SqlParserCS(它也覆盖 MySQL / Postgres / 其他数据库)。添加一种方言只需要一个实现 IDialectExtractor 的小类,并在 Extractor.Pick 中注册;引擎本身无需改动。

有关完整设计和已完成的 Northwind 工作示例,请参阅 README.md。

相关技能