摘要: Text2SQL 的核心,是让大模型根据数据库 Schema,把自然语言转换成 SQL,再交给数据库执行。本文用 SQLite 搭建一个最小 Demo,跑通查询、新增、修改以及多表 JOIN。
1. Text2SQL 是什么
平时查询数据库需要自己写 SQL:
ini
SELECT name, salary
FROM employees
WHERE department = '工程';
有了 Text2SQL,用户可以直接说:
工程部门员工的姓名和工资是多少?
系统完成:
sql
自然语言
↓
LLM 生成 SQL
↓
SQLite 执行 SQL
↓
返回数据
所以 Text2SQL 本质就是:
自然语言 → SQL
2. 用 SQLite 准备数据库
SQLite 是一个文件型关系数据库,不需要单独启动数据库服务。
Python 可以直接使用:
ini
import sqlite3
conn = sqlite3.connect("test.db")
cursor = conn.cursor()
这里:
sql
conn → 数据库连接
cursor → 执行 SQL
创建员工表:
python
cursor.execute("""
CREATE TABLE IF NOT EXISTS employees (
id INTEGER PRIMARY KEY,
name TEXT,
department TEXT,
salary INTEGER
)
""")
然后批量插入数据:
scss
sample_data = [ (6, "黄佳", "销售", 50000), (7, "宁宁", "工程", 75000), (8, "千千", "销售", 60000), (9, "岳岳", "工程", 80000), (10, "黄仁", "市场", 55000)]
cursor.executemany(
"INSERT INTO employees VALUES (?,?,?,?)",
sample_data
)
conn.commit()
这就是当前 Demo 的基础数据库。
3. 为什么必须把 Schema 给模型
如果只问模型:
工程部门员工的姓名和工资是多少?
它并不知道数据库中:
员工表叫 employees
姓名字段叫 name
工资字段叫 salary
部门字段叫 department
所以需要把数据库 Schema 一起给它。
SQLite 可以通过:
scss
schema = cursor.execute(
"PRAGMA table_info(employees)"
).fetchall()
获取表结构,再整理成:
sql
CREATE TABLE employees (
id INTEGER,
name TEXT,
department TEXT,
salary INTEGER
)
当前 Demo 就是通过 PRAGMA table_info() 自动获取 Schema。
于是模型真正接收到的是:
diff
Schema
+
用户问题
这才有足够的信息生成正确 SQL。
4. 实现 Text2SQL
核心函数其实很简单:
ini
def ask_deepseek(query, schema):
prompt = f"""
这是一个数据库的Schema:
{schema}
根据这个Schema,请输出一个SQL查询来回答以下问题。
只输出SQL查询语句本身,不要使用Markdown格式。
问题:{query}
"""
response = client.chat.completions.create(
model="deepseek-v4-flash",
max_tokens=2048,
messages=[{
"role": "user",
"content": prompt
}]
)
return response.choices[0].message.content
也就是:
markdown
question + schema
↓
LLM
↓
SQL
例如:
ini
question = "工程部门员工的姓名和工资是多少?"
sql_query = ask_deepseek(
question,
schema_str
)
模型生成:
ini
SELECT name, salary
FROM employees
WHERE department = '工程';
再执行:
scss
results = cursor.execute(sql_query).fetchall()
就完成了一次完整的 Text2SQL 查询。
5. 不只是查询,还能修改数据库
因为模型最终生成的是 SQL,所以它不仅能生成 SELECT。
例如:
在销售部门增加一个新员工,
姓名为张三,工资为45000
模型可以生成:
sql
INSERT INTO employees
(name, department, salary)
VALUES ('张三', '销售', 45000);
执行:
scss
cursor.execute(sql_query)
conn.commit()
更新也是一样:
将千千的工资调整为55000
生成:
ini
UPDATE employees
SET salary = 55000
WHERE name = '千千';
所以整个流程始终没有变化:
sql
自然语言
→ SQL
→ 数据库执行
6. 多表 Text2SQL
Demo 后面又增加了一张部门表:
bash
departments
├── id
├── name
└── manager
这时候就不能只把 employees 的 Schema 给模型了,而是要把整个数据库结构都提供进去。
例如:
scss
employees(...)
departments(...)
当前 Demo 已经通过循环自动获取两张表的 Schema。
于是对于:
列出每个部门的员工人数和平均工资
模型可以生成 JOIN:
sql
SELECT
d.name,
COUNT(e.id),
AVG(e.salary)
FROM departments d
LEFT JOIN employees e
ON d.name = e.department
GROUP BY d.id, d.name;
这时 Text2SQL 就从:
单表查询
进一步发展到了:
sql
理解多个表
→ 判断表之间的关系
→ 生成 JOIN
7. 最后理解整条链路
到目前这个 Demo,其实只需要记住:
scss
SQLite
↓
保存真实数据
PRAGMA table_info()
↓
获取 Schema
Schema + 用户问题
↓
LLM
SQL
↓
cursor.execute()
数据库查询 / 修改
所以:
SQLite 负责存储和执行 SQL,Text2SQL 负责把自然语言转换成 SQL。
而随着数据库越来越复杂,Text2SQL 真正的难点也会逐渐从"会不会写 SQL",变成:
模型是否真正理解数据库 Schema、字段含义以及表之间的关系。