用 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,前端输入问题 → 返回表格数据。
相关推荐
全栈老石1 小时前
别再折腾端口转发了:使用 Cloudflare Tunnel 优雅地分享你的 localhost
前端·后端·全栈
Mintopia4 天前
🚀 AIGC 如何重塑 Web 内容生产的价值链 —— 一场“硅基文艺复兴”的技术变革
人工智能·aigc·全栈
LYFlied5 天前
在AI时代,前端开发者如何构建全栈开发视野与核心竞争力
前端·人工智能·后端·ai·全栈
pixle06 天前
从零学习Node.js框架Koa 【七】Koa实战:构建企业级邮箱验证注册系统
javascript·学习·node.js·koa·注册·全栈·邮箱注册
用户47949283569158 天前
CVE-2025-55182:React 史上最严重漏洞,CVSS 满分 10.0
安全·react.js·全栈
Mintopia8 天前
🤖 大模型AI对话系统:消息结构展示设计猜想
人工智能·llm·全栈
Mintopia9 天前
🏗️ 系统架构之:大模型 Token 计费方案
人工智能·架构·全栈
汤姆Tom12 天前
前端转战后端:JavaScript 与 Java 对照学习指南(第四篇 —— List)
前端·编程语言·全栈
czc66613 天前
【项目实战】如何设计一个可以无限叠楼并且支持一键跳转目标的游标评论树?
全栈
Mintopia13 天前
🚀 2025全栈架构方案汇总与未来分析
人工智能·架构·全栈