SQL验证器是Schema Tools的一个独立模块,用于验证Question-SQL对中的SQL语句是否有效。它通过执行EXPLAIN
语句来检测SQL语法错误和表结构问题。
python -m schema_tools.sql_validator \
--db-connection "postgresql://user:pass@localhost:5432/dbname" \
--input-file ./qs_highway_db_20240101_143052_pair.json
python -m schema_tools.sql_validator \
--db-connection "postgresql://user:pass@localhost:5432/dbname" \
--input-file ./data.json \
--output-dir ./validation_reports
python -m schema_tools.sql_validator \
--db-connection "postgresql://user:pass@localhost:5432/dbname" \
--input-file ./data.json \
--max-concurrent 10 \
--batch-size 20 \
--timeout 60 \
--verbose
python -m schema_tools.sql_validator \
--db-connection "postgresql://user:pass@localhost:5432/dbname" \
--input-file ./data.json \
--dry-run
# 调整性能参数
python -m schema_tools.sql_validator \
--db-connection "postgresql://user:pass@localhost:5432/dbname" \
--input-file ./data.json \
--max-concurrent 10 \
--batch-size 20 \
--timeout 60 \
--verbose
# 基本使用(仅验证,不修改文件)
python -m schema_tools.sql_validator \
--db-connection "postgresql://user:pass@localhost:5432/dbname" \
--input-file ./data.json
# 启用LLM修复功能
python -m schema_tools.sql_validator \
--db-connection "postgresql://user:pass@localhost:5432/dbname" \
--input-file ./data.json \
--enable-llm-repair
# 预检查模式(仅验证文件格式)
python -m schema_tools.sql_validator \
--db-connection "postgresql://user:pass@localhost:5432/dbname" \
--input-file ./data.json \
--dry-run
import asyncio
from schema_tools import SQLValidationAgent
async def validate_sqls():
agent = SQLValidationAgent(
db_connection="postgresql://user:pass@localhost:5432/dbname",
input_file="./qs_highway_db_20240101_143052_pair.json",
output_dir="./validation_reports"
)
report = await agent.validate()
print(f"验证完成:")
print(f" 总SQL: {report['summary']['total_questions']}")
print(f" 有效: {report['summary']['valid_sqls']}")
print(f" 成功率: {report['summary']['success_rate']:.1%}")
asyncio.run(validate_sqls())
SQL验证器现在支持自动修改原始JSON文件:
# 默认仅验证,不修改原文件
python -m schema_tools.sql_validator \
--db-connection "postgresql://user:pass@localhost:5432/dbname" \
--input-file ./data.json
执行后:
sql_validation_时间戳_summary.txt
# 仅删除无效SQL,不进行LLM修复
python -m schema_tools.sql_validator \
--db-connection "postgresql://user:pass@localhost:5432/dbname" \
--input-file ./data.json \
--modify-original-file
执行后:
data.json.backup
data.json
(删除验证失败的SQL)file_modifications_时间戳.log
sql_validation_时间戳_summary.txt
# 启用LLM修复功能(需要同时指定文件修改参数)
python -m schema_tools.sql_validator \
--db-connection "postgresql://user:pass@localhost:5432/dbname" \
--input-file ./data.json \
--enable-llm-repair \
--modify-original-file
执行后:
data.json.backup
data.json
(更新修复成功的SQL,删除无法修复的SQL)file_modifications_时间戳.log
sql_validation_时间戳_summary.txt
每次修改都会生成详细的修改日志文件:
原始JSON文件修改日志
==================================================
修改时间: 2024-01-01 15:30:45
原始文件: ./qs_highway_db_20240101_143052_pair.json
备份文件: ./qs_highway_db_20240101_143052_pair.json.backup
修改的SQL (3个):
----------------------------------------
1. 索引: 5
问题: 查询订单与车辆数据的相关性分析?
原SQL: SELECT EXTRACT(year FROM oper_date) AS 年份, COUNT(*) FROM bss_business_day_data GROUP BY 年份;
新SQL: SELECT EXTRACT(year FROM oper_date)::integer AS 年份, COUNT(*) FROM bss_business_day_data GROUP BY EXTRACT(year FROM oper_date);
删除的无效项 (2个):
----------------------------------------
1. 索引: 12
问题: 查询不存在的表数据?
SQL: SELECT * FROM non_existent_table;
错误: relation "non_existent_table" does not exist
## 输入文件格式
SQL验证器接受标准的Question-SQL对JSON文件,格式如下:
```json
[
{
"question": "按服务区统计每日营收趋势(最近30天)?",
"sql": "SELECT service_name AS 服务区, oper_date AS 营业日期, SUM(pay_sum) AS 每日营收 FROM bss_business_day_data WHERE oper_date >= CURRENT_DATE - INTERVAL '30 day' AND delete_ts IS NULL GROUP BY service_name, oper_date ORDER BY 营业日期 ASC;"
},
{
"question": "查看车流量最大的前10个服务区",
"sql": "SELECT service_name AS 服务区, SUM(car_count) AS 总车流量 FROM bss_car_day_count WHERE delete_ts IS NULL GROUP BY service_name ORDER BY 总车流量 DESC LIMIT 10;"
}
]
验证完成后,默认只生成一个文本摘要报告:
sql_validation_时间戳_summary.txt
如果需要程序化处理验证结果,可以启用详细JSON报告:
# 启用JSON报告
python -m schema_tools.sql_validator \
--db-connection "postgresql://user:pass@localhost:5432/dbname" \
--input-file ./data.json \
--save-json
🚀 开始SQL验证...
📁 输入文件: ./qs_highway_db_20240101_143052_pair.json
🔗 数据库: postgresql://***:***@localhost:5432/highway_db
📦 处理批次 1/5 (10 个SQL)
✅ 批次 1 完成: 9/10 有效
📊 验证报告已保存: output/sql_validation_20240101_150000_summary.txt
🎉 验证完成,成功率: 90.0%
📊 详细结果: 45/50 SQL有效
SQL验证报告
==================================================
输入文件: ./qs_highway_db_20240101_143052_pair.json
验证时间: 2024-01-01T15:00:00
验证耗时: 2.45秒
验证结果摘要:
总SQL数量: 50
有效SQL: 45
无效SQL: 5
成功率: 90.00%
平均耗时: 0.049秒
重试次数: 0
SQL修复统计:
尝试修复: 5
修复成功: 3
修复失败: 2
修复成功率: 60.00%
原始文件修改统计:
修改的SQL: 3
删除的无效项: 2
修改失败: 0
错误详情(共2个):
==================================================
1. 问题: 查询订单与车辆数据的相关性分析?
错误: 函数 round(double precision, integer) 不存在
LLM修复尝试: 失败
修复失败原因: 无法识别正确的函数语法
完整SQL:
SELECT a.oper_date, a.order_sum AS 订单数量, b.customer_count AS 车辆数量,
ROUND(CORR(a.order_sum, b.customer_count), 2) AS 相关系数
FROM bss_business_day_data a
JOIN bss_car_day_count b ON a.oper_date = b.count_date;
----------------------------------------
成功修复的SQL(共3个):
==================================================
1. 问题: 各区域管理公司单位能耗产出对比(需结合能耗表)
原始错误: 对于表"e",丢失FROM子句项
修复后SQL:
SELECT c.company_name AS 公司名称,
ROUND(SUM(b.pay_sum)::numeric/SUM(b.order_sum)::numeric, 2) AS 单位订单产出
FROM bss_company c
JOIN bss_service_area sa ON c.id = sa.company_id
JOIN bss_business_day_data b ON sa.service_area_no = b.service_no
WHERE b.oper_date BETWEEN '2023-01-01' AND '2023-03-31'
GROUP BY c.company_name
ORDER BY 单位订单产出 DESC;
----------------------------------------
SQL验证器的配置位于 schema_tools/config.py
中:
"sql_validation": {
"reuse_connection_pool": True, # 复用现有连接池
"max_concurrent_validations": 5, # 并发验证数
"validation_timeout": 30, # 单个验证超时(秒)
"batch_size": 10, # 批处理大小
"continue_on_error": True, # 错误时是否继续
"save_validation_report": True, # 保存验证报告
"readonly_mode": True, # 启用只读模式
"max_retry_count": 2, # 验证失败重试次数
"report_file_prefix": "sql_validation", # 报告文件前缀
}
参数 | 类型 | 必需 | 说明 |
---|---|---|---|
--db-connection |
string | 是 | PostgreSQL数据库连接字符串 |
--input-file |
string | 是 | 输入的JSON文件路径 |
--output-dir |
string | 否 | 验证报告输出目录 |
--max-concurrent |
int | 否 | 最大并发验证数 |
--batch-size |
int | 否 | 批处理大小 |
--timeout |
int | 否 | 单个SQL验证超时时间(秒) |
--verbose |
flag | 否 | 启用详细日志输出 |
--log-file |
string | 否 | 日志文件路径 |
--dry-run |
flag | 否 | 仅读取和解析文件,不执行验证 |
max_concurrent_validations
batch_size
以减少内存占用validation_timeout
reuse_connection_pool
以减少连接开销连接失败
解决:检查数据库连接字符串和网络连通性
权限不足
解决:确保数据库用户有SELECT权限
表不存在
解决:检查SQL中的表名是否正确,注意schema前缀
语法错误
解决:检查SQL语法,注意PostgreSQL的语法特性
--verbose
获取详细日志--dry-run
预检查文件格式--batch-size
以便定位问题SQLSQL验证器可以与Schema Tools的其他模块无缝集成:
# 先生成Question-SQL对
from schema_tools import QuestionSQLGenerationAgent
qs_agent = QuestionSQLGenerationAgent(...)
qs_report = await qs_agent.generate()
# 然后验证生成的SQL
from schema_tools import SQLValidationAgent
sql_agent = SQLValidationAgent(
db_connection="...",
input_file=qs_report['output_file']
)
validation_report = await sql_agent.validate()