用AI工具搭建SQL检测脚本Skill让测试数据的脏坑无处可藏很多做软件测试的同学每天大量时间其实不是花在“找Bug”上而是耗在“搞数据”上。想验证一个订单超时退款的功能先得手工往数据库里改状态想核对分页查询的边界要自己写一段很长的条件SQL想确认一批历史数据有没有脏数据得反复执行几个看似简单但很容易漏条件的查询。这些事情本身不难难的是重复、费时、容易看走眼。更尴尬的是当你把这些活儿交给AI时它往往只会给你一段“看起来对”的SQL你需要自己再粘贴到客户端、切库、执行、盯结果。一旦表名、注释、字段类型出了问题来回调试的时间比自己写还长。这个痛点的根源不是AI不够聪明而是交互方式不对。普通的AI对话是一种“问答式服务”你问一句它答一句缺少任务边界、缺少规则约束、缺少可复用的执行模板。真正适合测试场景的是一种更结构化的协作方式把SQL检测的意图、规则、检查项、输出格式全部打包成一个“技能包”让AI在遇到类似任务时按固定流程执行。这就是本文要讲的Skill机制也是在软件测试场景中落地AI提效最值得先做的一步。这篇文章会围绕“如何用AI工具搭建一个面向SQL检测场景的Skill”展开包含Skill的基础概念、目录设计、最小可运行示例、常见报错排查方式和工程化建议。无论你是纯功能测试、测开还是日常兼职写SQL的研发只要手头有任何一个支持Skill机制的AI编程工具都能按同样的思路把它接进自己的工作流。文章最后还会把Skill的思路扩展到接口数据校验、自动化测试数据准备、UI自动化断言管理等7个测试场景帮助你把“某一次提效”变成“团队可复用的效率资产”。1. Skill不是聊天记录而是一套“技能封装”先确认一个容易混淆的点Skill不是网上流传的那种学习资料压缩包而是当前主流AI工具中一种“完成任务的标准件”。比如Claude相关工具里的Skill目录、Codex里的自定义技能、各类Agent框架中的Plugin本质上都在做同一件事提前告诉AI遇到某一类任务时该参考什么约束、调用哪些函数、生成什么格式的结果。你可以把Skill理解成“岗位说明书”。以前你让AI干活相当于给一个能力很强但没有经验的实习生口头派活你交代得越清楚他做对的概率越高但每次都要重新交代。Skill则等于给这个实习生一份写好的SOP任务触发条件是什么、环境是什么、要先检查什么、什么情况要拒绝执行、最终输出长什么样。AI看到这类任务时先加载SOP再动手产出质量自然比自由发挥稳定得多。和传统代码脚本相比Skill的差异点也很明显。对比维度普通SQL脚本AI写SQL后人工执行Skill封装后的AI执行任务触发自己开口自己开口描述意图自动触发技能规则约束靠个人记忆靠提示词临时约定技能内固定逻辑校验能力无只输出结果手动排查规则内置输出包含风险提示可复用性单文件可复用每次重新协商多场景统一入口团队复制看个人注释看聊天记录直接复制技能目录从表格里可以看出Skill最终解决的其实是“隐性经验显性化”的问题。测试同学脑子里的那些表结构注意事项、字段口径定义、危险操作规避习惯过去只能靠口头传递现在全部写进技能描述和规则文件里。团队里任何人用AI做SQL检测拿到的都是同一套经过检验的约束条件。2. 适合用Skill解决的软件测试常见场景不是所有测试任务都需要Skill。如果只是临时问一个函数用法或者写一条一次性SQL直接用对话窗口就够了。Skill的投入产出比最高的是“重复出现、规则明确、出错代价高”的任务。以下七类测试场景从实操价值来看最适合先做成SkillSQL数据准备与清理造数、清数据、重置状态、批量更新这类操作必须先做影响行数预估再决定是否提交。数据正确性校验统计测试前后的记录数、累计金额、状态分布需要固定口径不能每次让AI猜。结果集合理性检查检查查询结果中是否存在明显的空值、重复值、范围越界值这类检查规则稳定。慢查询与索引诊断测试环境下观察SQL执行计划判断是否走了全表扫描是否需要补充索引这需要输出结构化诊断结果。日志与错误排查根据应用日志中的报错反向推导SQL语句或数据状态这种跨文件检索非常适合Skill封装。接口自动化测试的数据断言接口返回结果需要和数据库实际状态做比对将SQL查询封装成可调用的工具函数。自动化脚本中的数据工厂UI自动化或接口自动化执行前准备符合业务规则的测试数据。这七个场景有一个共同点都涉及“先查数、再判断、然后动作”。如果把这些判断动作交给AI自由发挥往往会出现“AI认为没问题但实际业务上很有问题”的尴尬。Skill的意义就是把“判断动作”固化成规则让AI执行时自带风险意识。3. 环境准备搭建Skill前需要哪些条件在开始搭建Skill之前先检查一下手头工具是否满足条件。虽然不同AI工具的Skill机制名称不同但核心要求一致工具支持读取本地目录中的技能说明文件并能调用脚本或命令行工具执行任务。从通用实践来看建议准备以下环境操作系统Windows 10/11、macOS或主流Linux发行版均可无特殊限制。AI工具支持Skill目录机制的编程助手例如Claude Code、Codex CLI等。安装方式请参考对应工具的官方文档本文不绑定某一款具体工具。Python3.9及以上版本用于编写本地检测脚本。如果你更熟悉Node.js或Shell也可以替换本文示例用Python是为了通用性。数据库客户端根据实际测试环境选择MySQL、PostgreSQL、SQLite等。演示阶段建议先用SQLite避免权限和网络问题干扰。版本管理建议为Skill目录单独建一个Git仓库方便团队共享和回溯变更。需要特别强调一点Skill机制各家实现有差异但核心思路趋同。如果你的工具不支持目录型Skill也可以退而求其次将规则写入系统提示词或项目级规则文件中依然能获得80%的效果。4. 核心概念Skill目录、SKILL.md与规则文件在动手之前先把Skill涉及的几个核心概念弄清楚。一个完整的Skill通常由三部分组成4.1 Skill目录Skill目录是一个独立文件夹名称就是技能名建议使用短横线命名法。例如sql-inspector表示SQL检测技能test-data-factory表示测试数据工厂技能。目录内部一般包含技能说明和脚本文件。4.2 SKILL.md这是Skill的入口文件用Markdown编写。AI工具在判断是否触发该技能时会先读取这个文件。文件内容需要说明技能的用途、触发条件、使用步骤和注意事项。从实际工程角度来看SKILL.md写得越清楚AI触发准确率越高。很多Skill不可用不是脚本写得差而是描述文件太模糊导致AI不知道该不该用、什么时候用。4.3 规则文件与脚本规则文件用来存放结构化的检测规则常见格式是YAML或JSON。脚本则负责真正执行检测逻辑。脚本可以是Python、Shell、Node.js等任何形式AI工具负责识别任务、组织参数、调用脚本。当一个Skill同时包含描述、规则、脚本三种内容时它就已经从“一段提示词”进化为“一个可执行工具”。团队内部可以直接复制整个目录到任何项目里复用。5. 完整示例从零搭建一个SQL检测脚本Skill下面通过一个最小可运行的示例演示如何搭建一个SQL检测Skill。这个Skill的名称为sql-inspector核心功能是当测试人员提交一条SQL查询时AI先对SQL文本做静态风险检查然后连接数据库查看执行计划最后输出风险等级和处理建议。5.1 目录结构skills/ └── sql-inspector/ ├── SKILL.md ├── rules.yaml ├── scripts/ │ └── inspect.py └── output_template.md5.2 编写SKILL.md--- name: sql-inspector description: 用于检查SQL查询语句的潜在风险和正确性问题。当用户提供SQL、表名、查询条件或要求验证一条查询是否能安全用于测试数据核对时使用此技能。 --- # SQL 检测助手 这个技能帮助测试人员检查SQL查询语句发现潜在风险。 ## 适用场景 - 测试数据准备完成后需要核验数据量是否符合预期。 - 编写了SQL查询但不确定是否缺少关键条件。 - 需要判断查询语句是否会对数据库造成较大压力。 - 需要比较两条SQL的结果差异时作为辅助检查工具。 ## 使用步骤 1. 接收用户输入的SQL语句。 2. 解析SQL中的关键关键字如 SELECT、UPDATE、DELETE、WHERE、LIMIT。 3. 调用脚本 scripts/inspect.py传入SQL文本和数据库连接参数。 4. 根据脚本输出生成风险报告。 5. 如果风险等级为 HIGH明确建议用户不要直接执行。 ## 注意事项 - 只允许在测试环境或已授权数据库上执行实际操作。 - 对 UPDATE 和 DELETE 语句必须强制检查是否包含 WHERE 条件。 - 输出报告必须包含风险等级和处理建议。5.3 定义规则文件# rules.yaml rules: - id: NO_WHERE description: 查询语句缺少WHERE条件 severity: HIGH keywords: - update - delete - id: NO_LIMIT description: SELECT语句没有LIMIT限制 severity: MEDIUM keywords: - select - id: SELECT_ALL_COLUMNS description: 使用SELECT *查询所有字段 severity: MEDIUM keywords: - select * - id: POTENTIAL_EMPTY_RESULT description: 查询条件过于简单可能导致结果集为空 severity: LOW condition: where_columns_is_empty5.4 编写检测脚本# 文件路径skills/sql-inspector/scripts/inspect.py #!/usr/bin/env python3 SQL 静态风险检测脚本 用法示例 python inspect.py --sql select * from orders where id 100 --db sqlite:///test.db 注意 1. 本脚本仅执行静态分析和轻量查询不会修改数据库数据。 2. UPDATE/DELETE 语句不会实际执行只做文本规则检查。 3. 请确保在授权环境下使用。 import argparse import re import sqlite3 import sys def parse_args(): parser argparse.ArgumentParser(descriptionSQL静态风险检测) parser.add_argument(--sql, requiredTrue, help需要检查的SQL语句) parser.add_argument(--db, default, help数据库连接串例如 sqlite:///test.db可为空) return parser.parse_args() def check_no_where(sql_lower): 检查UPDATE/DELETE是否缺少WHERE条件。 if (update in sql_lower or delete in sql_lower) and where not in sql_lower: return { rule_id: NO_WHERE, severity: HIGH, message: UPDATE/DELETE语句缺少WHERE条件可能导致全表数据被修改, suggestion: 请补充明确的WHERE条件或先使用SELECT确认影响范围, } return None def check_no_limit(sql_lower): 检查SELECT是否缺少LIMIT限制。 if sql_lower.startswith(select) and limit not in sql_lower: return { rule_id: NO_LIMIT, severity: MEDIUM, message: SELECT查询未添加LIMIT限制, suggestion: 建议在测试数据核对时添加LIMIT避免返回过多结果, } return None def check_select_all(sql_lower): 检查是否存在SELECT *查询。 pattern re.compile(rselect\s\*) if pattern.search(sql_lower): return { rule_id: SELECT_ALL_COLUMNS, severity: MEDIUM, message: 使用SELECT *查询所有字段, suggestion: 建议只查询需要核对的字段避免不必要的数据传输, } return None def check_duplicate_keywords(sql_lower): 简单检查是否存在明显重复的关键字。 if sql_lower.count(select) 1: return { rule_id: COMPLEX_SQL, severity: LOW, message: SQL语句包含多个SELECT关键字可能存在子查询或联合查询, suggestion: 请确认查询逻辑是否符合预期必要时拆分为多个步骤, } return None def run_static_checks(sql_text): 运行所有静态检查规则。 sql_lower sql_text.lower() checks [ check_no_where(sql_lower), check_no_limit(sql_lower), check_select_all(sql_lower), check_duplicate_keywords(sql_lower), ] results [item for item in checks if item is not None] return results def try_query_with_sqlite(sql_text, sqlite_path): 如果SQLite文件存在尝试执行EXPLAIN QUERY PLAN。 该操作不会修改数据只返回执行计划。 try: conn sqlite3.connect(sqlite_path) cursor conn.cursor() cursor.execute(fEXPLAIN QUERY PLAN {sql_text}) rows cursor.fetchall() conn.close() return rows except Exception as exc: return f查询执行计划失败: {exc} def main(): args parse_args() sql_text args.sql.strip() if not sql_text: print(json.dumps({error: SQL不能为空}, ensure_asciiFalse)) sys.exit(1) # 1. 静态规则检查 rule_results run_static_checks(sql_text) # 2. 如果指定了SQLite文件进一步查看执行计划 plan_result if args.db.startswith(sqlite:///): db_path args.db.replace(sqlite:///, ) plan_result try_query_with_sqlite(sql_text, db_path) # 3. 计算整体风险等级 has_high any(item[severity] HIGH for item in rule_results) has_medium any(item[severity] MEDIUM for item in rule_results) if has_high: overall_level HIGH elif has_medium: overall_level MEDIUM else: overall_level LOW output { sql: sql_text, overall_risk_level: overall_level, rule_results: rule_results, execute_plan: plan_result, } # 输出JSON结果方便AI工具解析 import json print(json.dumps(output, ensure_asciiFalse, indent2)) if __name__ __main__: main()5.5 编写输出格式模板# SQL 检测结果 ## 风险等级 - 总体风险等级{{overall_risk_level}} ## 规则检查项 {% for item in rule_results %} ### 问题 {{ loop.index }} - 规则ID{{ item.rule_id }} - 严重程度{{ item.severity }} - 说明{{ item.message }} - 建议{{ item.suggestion }} {% endfor %} ## 执行计划{{ execute_plan }}以上五个文件构成了一个最小可用的SQL检测Skill。这个Skill的核心思路是AI工具负责解析用户输入、组装参数、调用脚本Python脚本负责执行规则检测最后将结构化结果转为人类可读的风险报告。6. 运行验证如何判断Skill生效并输出正确结果Skill搭建完成后第一步是用命令行直接验证脚本本身是否正常绕过AI工具单独测试便于排查问题。在项目根目录下执行以下命令cd skills/sql-inspector python scripts/inspect.py --sql select * from orders --db sqlite:///test.db如果test.db不存在会输出执行计划失败的信息但静态规则检查照常工作。预期输出如下关键字段节选{ sql: select * from orders, overall_risk_level: MEDIUM, rule_results: [ { rule_id: NO_LIMIT, severity: MEDIUM, message: SELECT查询未添加LIMIT限制, suggestion: 建议在测试数据核对时添加LIMIT避免返回过多结果 }, { rule_id: SELECT_ALL_COLUMNS, severity: MEDIUM, message: 使用SELECT *查询所有字段, suggestion: 建议只查询需要核对的字段避免不必要的数据传输 } ], execute_plan: 查询执行计划失败: ... }观察输出结果时需要确认三点rule_results中是否按预期识别出缺少LIMIT和SELECT *的问题。overall_risk_level是否为MEDIUM说明风险等级聚合逻辑生效。execute_plan字段如果报错是因为本机没有创建test.db这一步不影响静态检测的正确性。为了进一步验证HIGH风险场景可以执行如下命令python scripts/inspect.py --sql update orders set status 1预期输出中会包含NO_WHERE规则风险等级变为HIGH。看到这个结果说明脚本已经具备基本的合规拦截能力。命令行验证通过后再进入AI工具中测试。将Skill目录放到AI编程工具能读取的位置然后输入一条贴近日常工作的请求帮我检查这条SQLselect * from orders where create_time 2025-01-01我准备在测试环境核对数据量。如果Skill触发成功AI会先调用inspect.py再根据脚本输出生成一份风险报告并主动提醒是否需要补LIMIT或去掉SELECT *。如果AI没有触发技能只给出普通文本回答常见原因是SKILL.md中的描述与用户请求的匹配度不够或工具读取Skill目录的路径配置不正确。7. 常见问题与排查路径在落地Skill的过程中最容易遇到的四类问题值得单独梳理。这些问题大多不是代码逻辑错误而是工具协作层面的设置问题。问题现象可能原因排查方式解决方案AI没有触发Skill只做普通回答SKILL.md中的description与用户请求不匹配查看AI工具的调试日志或Verbose输出精简description添加用户常用说法作为触发词脚本能运行但AI报“无法识别命令”工作目录或PATH配置错误在Skill配置中显式写明脚本绝对路径或相对路径将路径写入SKILL.md避免依赖当前目录高风险的UPDATE语句被AI直接执行规则检查结果未被AI读取确认脚本输出中是否包含overall_risk_level字段在SKILL.md中增加“必须根据风险等级决定是否执行”的指令Skill在A项目可用B项目不可用未将Skill目录纳入B项目白名单检查各AI工具的workspace配置将Skill作为一个子模块在需要项目中执行安装命令脚本输出中文乱码Windows终端编码问题检查终端代码页是否为UTF-8在Python脚本中设置sys.stdout.reconfigure(encodingutf-8)针对“脚本输出乱码”这个问题补充一个通用修复方法。在脚本main()前增加以下代码可以确保Windows下输出正常# 解决Windows下部分终端的中文输出乱码问题 import sys if sys.stdout.encoding and sys.stdout.encoding.lower() ! utf-8: sys.stdout.reconfigure(encodingutf-8)对于直接操作数据库的测试脚本也要在SKILL.md中强制加入安全约束。示例描述如下## 安全约定 - 本技能只允许在测试环境连接字符串上执行。 - 所有UPDATE/DELETE操作必须先通过SELECT确认影响行数。 - 如果连接串包含生产环境关键字立即停止执行并输出警告。 - 不向任何外部接口发送查询到的数据内容。8. 从单个SQL Skill到7大测试场景SkillsSQL检测Skill跑通之后整套思路可以快速复制到其他测试场景。下面用一个统一的目录模板来说明如何将开篇提到的七类场景都沉淀成标准技能包。8.1 场景一数据准备与清理技能名称test-data-factory核心逻辑提前录入常用业务表的造数SQL模板AI收到“给订单模块造10条测试数据”的指令后先查当前最大ID再拼接INSERT语句最后执行并返回生成结果。这个技能的关键是让AI分两步走先确认环境再执行写入。8.2 场景二数据正确性校验技能名称># .env 示例文件请勿提交到Git仓库 TEST_DB_CONNECTIONsqlite:///test.db ALLOWED_ENVIRONMENTSdev,test9.4 所有写操作都要有“安全锁”在SKILL.md中增加硬性约定任何更新或删除操作必须分两步走。第一步生成SELECT语句由人确认影响行数第二步携带一个确认参数才能执行写操作。这个约定需要写进规则文件并在代码中明确检测。9.5 把Skill纳入版本管理Skill本身是一个目录天然适合用Git管理。建议在仓库中为每个Skill维护变更记录说明新增了哪条规则、修改了哪个脚本。这不仅是文档规范更是为了在AI生成行为异常时能快速回滚到上一版本。9.6 先在小范围试点而不是一次性铺开一次创建七个Skill看起来高效但如果没有人使用迭代这些技能包很快就会因环境变化而失效。更务实的节奏是先挑一个你最常做的重复性任务比如SQL核对做成第一个Skill用两周时间迭代稳定后再复制到其他场景。10. 总结与后续学习方向SQL检测Skill的本质是把测试人员脑子里那些“安全的SQL长什么样”“执行前要注意什么”的隐性经验转化为AI能理解、能执行、能复用的显性规则。这套做法真正的价值不在于把一次SQL核对从几分钟压缩到几十秒而在于当团队里任何一个成员遇到同类问题时不必重新踩坑直接调用同一个技能包就能得到一致的输出质量。如果你正准备迈出第一步建议按以下顺序推进先选定一个每周至少出现三次的重复性SQL任务。用本文第五节的最小示例搭出第一个Skill命令行独立验证通过。在AI编程工具中挂载Skill用真实的测试库数据走一遍完整流程。让身边一位同事也使用同一个Skill收集反馈并调整规则。跑通后再向数据校验、日志解析、接口断言等场景复制。后续值得深入的方向有三个一是学习不同AI工具的Skill机制差异理解它们各自的上下文窗口和工具调用策略二是研究如何让Skill自动适应多种数据库方言而不是写死某一种数据库语法三是思考如何把Skill的检测结果接入CI流水线让每次测试环境数据变更都能自动跑一遍风险检查。当SQL检测Skill不依赖某一个人、某一个工具、某一次输入时它才算真正进入了工程化阶段。建议先收藏本文拿到工位旁边照着目录结构敲一遍用一个小型SQLite库验证后再逐步扩展到业务测试库。毕竟工具再好也得上手跑起来才算数。
