用大模型实现 Text2SQL:让业务人员也能轻松操作数据库

77 阅读4分钟

在日常开发或数据分析工作中,我们常常遇到这样的场景:

  • 产品经理想查一下“销售部门有哪些人,但不会写 SQL;
  • 运营同事需要临时加一个用户,却得麻烦后端工程师;
  • 财务小姐姐想看看“工资最高的三位员工是谁”,但连数据库长什么样都不知道……

这些看似简单的需求,却因为“不会写 SQL”而卡住。有没有一种方式,能让非技术人员像聊天一样操作数据库?

答案是:有!借助大语言模型(LLM)的 Text2SQL 能力,我们可以构建一个“自然语言 → SQL”的桥梁。

今天,我们就用 DeepSeek 的开源大模型 + SQLite,手把手实现一个轻量级但完整的 Text2SQL 系统!


🧠 核心思路:LLM + Schema 上下文 = 智能 SQL 生成器

Text2SQL 的关键在于:给大模型提供清晰的数据库结构(Schema)作为上下文,再让它根据自然语言问题生成对应的 SQL 语句。

我们的流程如下:

  1. 创建 SQLite 数据库和员工表;
  2. 提取表结构(Schema);
  3. 构造 Prompt,将 Schema + 用户问题喂给 LLM;
  4. LLM 返回纯 SQL;
  5. 执行 SQL 并返回结果。

整个过程无需人工干预,真正实现“说人话,查数据”。


🛠️ 实战代码解析

1. 初始化数据库

import sqlite3

conn = sqlite3.connect("test.db")
cursor = conn.cursor()

cursor.execute("""
CREATE TABLE IF NOT EXISTS employees(
    id INTEGER PRIMARY KEY,
    name TEXT,
    department TEXT,
    salary INTEGER
)
""")

sample_data = [
    (6, "黄佳", "销售", 50000),
    (7, "宁宁", "工程", 75000),
    (8, "谦谦", "销售", 60000),
    (9, "悦悦", "工程", 80000),
    (10, "黄仁勋", "市场", 55000)
]

cursor.executemany("INSERT INTO employees VALUES(?,?,?,?)", sample_data)
conn.commit()

注意:这里故意跳过 id=1~5,模拟真实系统中可能存在的 ID 不连续情况。


2. 获取 Schema 并格式化

schema = cursor.execute("PRAGMA table_info(employees)").fetchall()
schema_str = "CREATE TABLE EMPLOYEES (\n" + \
             "\n".join([f"{col[1]} {col[2]}" for col in schema]) + "\n)"

输出示例:

CREATE TABLE EMPLOYEES (
id INTEGER
name TEXT
department TEXT
salary INTEGER
)

这个结构会被注入到 Prompt 中,告诉 LLM:“数据库长这样,请按规矩出牌”。


3. 调用 DeepSeek 大模型生成 SQL

我们使用 DeepSeek 提供的 OpenAI 兼容 API:

from openai import OpenAI

client = OpenAI(
    api_key='',#这里使用自己的api_key
    base_url='https://api.deepseek.com/v1'#这里的平台不唯一
)

定义核心函数 ask_deepseek

def ask_deepseek(query, schema):
    prompt = f"""
这是一个数据库的Schema:
{schema}
根据这个Schema,请输出一个SQL查询来回答以下问题。
只输出SQL查询语句本身,不要使用任何Markdown格式,
不要包含反引号、代码块标记或额外说明。
问题: {query}
"""
    response = client.chat.completions.create(
        model="deepseek-chat",
        messages=[{"role": "user", "content": prompt}],
        temperature=0  # 确保输出稳定
    )
    return response.choices[0].message.content

关键点:temperature=0 避免随机性,确保每次生成一致;严格限制输出格式,只返回 SQL,便于后续执行。


4. 测试各种场景

✅ 查询类

question = "工程部门员工的姓名和工资是多少"
sql = ask_deepseek(question, schema_str)
# 输出:SELECT name, salary FROM employees WHERE department = '工程';

执行后得到:

[('宁宁', 75000), ('悦悦', 80000)]

✅ 插入类

question = "在销售部门增加一个新员工,姓名为张三,工资为45000"
sql = ask_deepseek(question, schema_str)
# 输出:INSERT INTO employees (name, department, salary) VALUES ('张三', '销售', 45000);

执行后,张三成功入库!

✅ 删除类

question = "删除市场部门的黄仁勋"
sql = ask_deepseek(question, schema_str)
# 输出:DELETE FROM employees WHERE department = '市场' AND name = '黄仁勋';

⚠️ 安全提示:生产环境中需对 DML(INSERT/UPDATE/DELETE)操作做权限控制或二次确认!

✅ 全表查询

question = "查询所有员工的信息"
sql = ask_deepseek(question, schema_str)
# 输出:SELECT id, name, department, salary FROM employees;

结果完整返回当前所有员工。


💡 为什么这很有价值?

  1. 降低数据库使用门槛:业务、运营、产品都能自助查数据;
  2. 提升开发效率:减少“帮我查个数据”的低效沟通;
  3. 可嵌入后台系统:打造 LLM 驱动的智能管理后台;
  4. 支持多表扩展:只需把多个表的 Schema 拼进去,LLM 也能处理 JOIN。

🌟 结语:数据库平权时代已来

通过 LLM 的 Text2SQL 能力,我们正在迈向一个“人人都是数据分析师”的时代。不需要记住 GROUP BY 的语法,也不用纠结单引号还是双引号——只要你会说话,就能操作数据库。

而这,正是 AI 赋能开发的本质:不是取代程序员,而是把重复劳动自动化,让人专注更高价值的创造。