用 LLM 自动生成 SQL:从 SQLite Schema 到自然语言查询的完整实践

一、为什么要做"自然语言转 SQL"?

在数据分析、低代码平台、BI 工具等场景中,非技术人员常因不会写 SQL 而无法自助查询数据。而借助 LLM(如 DeepSeek、GPT),我们可以:

  • 降低使用门槛:用户只需用自然语言提问(如"开发部员工工资多少?")
  • 提升开发效率:自动生成准确 SQL,减少人工编写与调试成本
  • 快速验证想法:原型阶段无需构建复杂 UI,一句话即可查数据

✅ 本文以 SQLite + DeepSeek API 为例,展示一个最小可行方案(MVP)。


二、技术栈与准备

组件 说明
数据库 SQLite(Python 内置,无需安装服务)
LLM 服务 DeepSeek(兼容 OpenAI API,国内可访问)
编程语言 Python 3.7+
依赖库 sqlite3(内置)、openai(用于调用 DeepSeek)

安装依赖:

复制代码
bash
编辑
pip install openai

三、完整实现步骤

步骤 1:创建 SQLite 表并插入示例数据

python 复制代码
python
编辑
import sqlite3

# 连接数据库(若不存在则自动创建)
conn = sqlite3.connect("text5.db")
cursor = conn.cursor()

# 创建 employees 表
cursor.execute("""
CREATE TABLE IF NOT EXISTS employees (
    id INTEGER PRIMARY KEY,      -- 注意:原文 PRINARY 是拼写错误,应为 PRIMARY
    name TEXT,
    department TEXT,
    salary INTEGER
)
""")

# 插入测试数据
sample_data = [
    (6, "陈老板", "开发部", 100000),
    (7, "张三", "销售部", 20000),
    (8, "李四", "开发部", 50000),
    (9, "王五", "销售部", 22000),
]
cursor.executemany('INSERT INTO employees VALUES (?, ?, ?, ?)', sample_data)
conn.commit()

⚠️ 注意 :原文中 PRINARY KEY 是拼写错误,正确应为 PRIMARY KEY,否则会创建成普通列!


步骤 2:提取表结构(Schema)

为了让 LLM 理解表结构,需提供清晰的 Schema 描述:

python 复制代码
python
编辑
# 获取表字段信息
schema = cursor.execute("PRAGMA table_info(employees)").fetchall()
# 构造 CREATE TABLE 风格的字符串
schema_str = "CREATE TABLE EMPLOYEES (\n" + "\n".join([f"    {col[1]} {col[2]}" for col in schema]) + "\n)"
print("数据库 Schema:")
print(schema_str)

输出示例:

sql 复制代码
sql
编辑
CREATE TABLE EMPLOYEES (
    id INTEGER
    name TEXT
    department TEXT
    salary INTEGER
)

💡 虽然缺少约束(如 PRIMARY KEY),但对简单查询已足够。更严谨的做法可解析 DDL 或补充注释。


步骤 3:调用 LLM 生成 SQL

使用 DeepSeek 的 Reasoner 模型(擅长推理任务):

ini 复制代码
python
编辑
from openai import OpenAI

client = OpenAI(
    api_key='sk-xxxx',  # 替换为你的 DeepSeek API Key
    base_url='https://api.deepseek.com/v1'
)

def ask_deepseek(query: str, schema: str) -> str:
    prompt = f"""
这是一个数据库的Schema:
{schema}
根据这个Schema,你能输出一个SQL查询来回答以下问题吗?
只输出SQL查询,不要输出任何其他内容。也不要带任何格式。
问题:{query}
"""
    response = client.chat.completions.create(
        model="deepseek-reasoner",
        max_tokens=2048,
        messages=[{"role": "user", "content": prompt}]
    )
    return response.choices[0].message.content.strip()

# 测试提问
question = "开发部部门员工的姓名和工资是多少?"
sql = ask_deepseek(question, schema_str)
print("生成的 SQL 查询:")
print(sql)

预期输出:

sql 复制代码
sql
编辑
SELECT name, salary FROM employees WHERE department = '开发部';

步骤 4:执行 SQL 并返回结果(可选)

scss 复制代码
python
编辑
result = cursor.execute(sql).fetchall()
print("查询结果:", result)
# 输出:[('陈老板', 100000), ('李四', 50000)]

四、关键技巧与注意事项

1. Prompt 设计要点

  • 明确指令:"只输出 SQL,不要解释"
  • 提供精确 Schema:字段名、类型必须一致
  • 示例引导(Few-shot) :复杂场景可加 1~2 个例子提升准确率

2. 常见问题与解决方案

问题 原因 解决方案
生成无效 SQL Schema 不清晰或字段名不匹配 使用 PRAGMA table_info 精确获取字段
返回多余文本 LLM 未严格遵循指令 在 Prompt 中强调"仅输出 SQL"
表名大小写错误 SQLite 默认小写 Schema 中统一用小写表名
拼写错误(如 PRINARY) 手动建表失误 建表时仔细检查语法

3. 安全警告 ⚠️

  • 切勿直接执行 LLM 生成的 SQL!
    应进行白名单校验 (如只允许 SELECT)、参数化查询,防止注入攻击。
  • 生产环境建议增加 SQL 解析器(如 sqlglot)做语法校验。

五、方案对比:不同实现方式优劣

方案 优点 缺点 适用场景
LLM 直接生成 SQL 快速、灵活、支持自然语言 可能出错、需校验 原型验证、内部工具
模板匹配 + 规则引擎 稳定、可控 扩展性差、需维护规则 固定查询模式
专用 NL2SQL 模型(如 SQLCoder) 准确率高 需部署模型、资源消耗大 企业级产品

✅ 对于个人项目或 MVP,LLM + Prompt 工程 是性价比最高的选择。


六、总结要点

  • ✅ SQLite 轻量易用,适合本地数据存储与测试
  • ✅ 通过 PRAGMA table_info 可程序化获取表结构
  • ✅ LLM(如 DeepSeek)能有效将自然语言转为 SQL
  • Prompt 要清晰、约束要明确
  • 永远不要信任 LLM 输出,必须校验 SQL 安全性

七、拓展思考

  1. 如何支持多表 JOIN 查询?
    → 在 Schema 中提供多个表的 DDL,并在问题中明确关联字段。
  2. 能否缓存常见问题的 SQL?
    → 可建立"问题- SQL"映射缓存,提升响应速度与稳定性。
  3. 如何评估生成 SQL 的准确率?
    → 构建测试集,用执行结果 vs 人工标注结果做比对。
  4. 前端集成?
    → 用 Flask/FastAPI 封装为 REST API,前端输入问题 → 返回表格数据。
相关推荐
Mintopia2 天前
🧠 Claude Code 接入 Context7 MCP:一场上下文扩展的浪漫协作
人工智能·claude·全栈
前端小万2 天前
芋道实战|34k开源项目的登录功能拆解
全栈
爱分享的鱼鱼3 天前
部署Vue+Java Web应用到云服务器完整指南
前端·后端·全栈
一颗苹果OMG4 天前
随着AI的发展,测试跟prompt会不会成为每个程序员的必修课
前端·程序员·全栈
Mintopia7 天前
Trae WebGen-solo模式快速完成项目
人工智能·全栈·trae
AAA阿giao8 天前
用 AI 工程师 Trae Solo ,一个人打造“绘本岛”:从想法到上线只需三步
人工智能·全栈·trae
浪遏10 天前
好久不见 ,甚是想念 | vibe coding 一个react native 全栈项目| 小账兜
react native·全栈·vibecoding
前端小万12 天前
芋道实战|34k开源项目如何新建模块?
全栈
Mintopia16 天前
🧠 Next.js × GraphQL Yoga × GraphiQL:交互式智能之门
前端·后端·全栈